Repository: inancgumus/learngo
Branch: master
Commit: 3c475a78e543
Files: 1533
Total size: 1.6 MB
Directory structure:
gitextract_uy2gop8w/
├── .gitignore
├── 01-get-started/
│ ├── README.md
│ ├── osx-installation.md
│ ├── programmers-roadmap.md
│ ├── ubuntu-installation.md
│ └── windows-installation.md
├── 02-write-your-first-program/
│ ├── README.md
│ ├── annotated-go-program-example.md
│ ├── exercises/
│ │ ├── 01-print-names/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ ├── main.go
│ └── questions/
│ ├── 01-gopath/
│ │ └── README.md
│ ├── 02-code-your-first-program/
│ │ └── README.md
│ └── 03-run-your-first-program/
│ └── README.md
├── 03-packages-and-scopes/
│ ├── 01-packages/
│ │ ├── bye.go
│ │ ├── hey.go
│ │ └── main.go
│ ├── 02-scopes/
│ │ ├── 01-scopes/
│ │ │ └── main.go
│ │ ├── 02-block-scope/
│ │ │ └── main.go
│ │ ├── 03-nested-scope/
│ │ │ └── main.go
│ │ └── 04-package-scope/
│ │ ├── bye.go
│ │ ├── hey.go
│ │ └── main.go
│ ├── 03-importing/
│ │ ├── 01-file-scope/
│ │ │ ├── bye.go
│ │ │ └── main.go
│ │ └── 02-renaming/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-packages/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ ├── bye.go
│ │ │ ├── greet.go
│ │ │ └── main.go
│ │ ├── 02-scopes/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ ├── main.go
│ │ │ └── printer.go
│ │ ├── 03-importing/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ ├── 01-packages-A/
│ │ └── README.md
│ ├── 02-packages-B/
│ │ └── README.md
│ └── 03-scopes/
│ └── README.md
├── 04-statements-expressions-comments/
│ ├── 01-statements/
│ │ ├── 01-execution-flow/
│ │ │ └── main.go
│ │ └── 02-semicolons/
│ │ └── main.go
│ ├── 02-expressions/
│ │ ├── 01-operator/
│ │ │ └── main.go
│ │ └── 02-call-expression/
│ │ └── main.go
│ ├── 03-comments/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-shy-semicolons/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-naked-expression/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-operators-combine/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-print-go-version/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-comment-out/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 06-use-godoc/
│ │ │ ├── exercise.md
│ │ │ └── solution/
│ │ │ └── solution.md
│ │ └── README.md
│ └── questions/
│ ├── 01-statements/
│ │ └── README.md
│ ├── 02-expressions/
│ │ └── README.md
│ └── 03-comments/
│ └── README.md
├── 05-write-your-first-library-package/
│ ├── exercise/
│ │ ├── README.md
│ │ └── solution/
│ │ └── golang/
│ │ ├── cmd/
│ │ │ └── main.go
│ │ └── go.go
│ ├── printer/
│ │ ├── cmd/
│ │ │ └── main.go
│ │ └── printer.go
│ └── questions/
│ └── README.md
├── 06-variables/
│ ├── 01-basic-data-types/
│ │ ├── exercises/
│ │ │ ├── 01-print-the-literals/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 02-print-hexes/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ └── README.md
│ │ ├── main.go
│ │ └── questions/
│ │ └── README.md
│ ├── 02-declarations/
│ │ ├── 01-declaration-syntax/
│ │ │ ├── 01-syntax/
│ │ │ │ └── main.go
│ │ │ ├── 02-naming-rules/
│ │ │ │ └── main.go
│ │ │ └── 03-order-of-declaration/
│ │ │ └── main.go
│ │ ├── 02-example-declarations/
│ │ │ ├── 01-int/
│ │ │ │ └── main.go
│ │ │ ├── 02-float64/
│ │ │ │ └── main.go
│ │ │ ├── 03-bool/
│ │ │ │ └── main.go
│ │ │ └── 04-string/
│ │ │ └── main.go
│ │ ├── 03-zero-values/
│ │ │ └── main.go
│ │ ├── 04-unused-variables-and-blank-identifier/
│ │ │ ├── 01-unused-variable/
│ │ │ │ └── main.go
│ │ │ └── 02-blank-identifier/
│ │ │ └── main.go
│ │ ├── 05-multiple-declarations/
│ │ │ ├── 01-multiple/
│ │ │ │ └── main.go
│ │ │ └── 02-parallel/
│ │ │ └── main.go
│ │ ├── 06-examples/
│ │ │ └── main.go
│ │ ├── exercises/
│ │ │ ├── 01-int/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 02-bool/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 03-float64/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 04-string/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 05-undeclarables/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 06-with-bits/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 07-multiple/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 08-multiple-2/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 09-unused/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 10-package-variable/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 11-wrong-doer/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ └── README.md
│ │ └── questions/
│ │ ├── 01-what/
│ │ │ └── README.md
│ │ ├── 02-declaration/
│ │ │ └── README.md
│ │ ├── 03-unused-variables/
│ │ │ └── README.md
│ │ └── 04-zero-values/
│ │ └── README.md
│ ├── 03-short-declaration/
│ │ ├── 01-initialization-and-short-declaration/
│ │ │ ├── 01-initialization/
│ │ │ │ └── main.go
│ │ │ ├── 02-short-declaration/
│ │ │ │ └── main.go
│ │ │ └── 03-coding-example/
│ │ │ └── main.go
│ │ ├── 02-package-scope/
│ │ │ └── main.go
│ │ ├── 03-multiple-short-declaration/
│ │ │ ├── 01-declaration/
│ │ │ │ └── main.go
│ │ │ ├── 02-coding-example/
│ │ │ │ └── main.go
│ │ │ └── 03-redeclaration/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ └── 02-coding-example/
│ │ │ └── main.go
│ │ ├── 04-short-vs-normal/
│ │ │ ├── 01-declaration/
│ │ │ │ └── main.go
│ │ │ └── 02-short-declaration/
│ │ │ └── main.go
│ │ ├── exercises/
│ │ │ ├── 01-short-declare/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 02-multiple-short-declare/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 03-multiple-short-declare-2/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 04-short-with-expression/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 05-short-discard/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 06-redeclare/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ └── README.md
│ │ └── questions/
│ │ └── README.md
│ ├── 04-assignment/
│ │ ├── 01-assignment/
│ │ │ ├── 01-assignment/
│ │ │ │ └── main.go
│ │ │ ├── 02-strongly-typed/
│ │ │ │ └── main.go
│ │ │ └── 03-examples/
│ │ │ └── main.go
│ │ ├── 01-overview/
│ │ │ └── main.go
│ │ ├── 05-multiple-assignment/
│ │ │ └── main.go
│ │ ├── 06-swapping/
│ │ │ └── main.go
│ │ ├── 07-path-project/
│ │ │ └── main.go
│ │ ├── 08-path-project-discarding/
│ │ │ └── main.go
│ │ ├── 09-path-project-shortdecl/
│ │ │ └── main.go
│ │ ├── exercises/
│ │ │ ├── 01-make-it-blue/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 02-vars-to-vars/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 03-assign-with-expressions/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 04-find-the-rectangle-perimeter/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 05-multi-assign/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 06-multi-assign-2/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 07-multi-short-func/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 08-swapper/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 09-swapper-2/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 10-discard-the-file/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ └── README.md
│ │ └── questions/
│ │ └── README.md
│ ├── 05-type-conversion/
│ │ ├── 01-destructive/
│ │ │ └── main.go
│ │ ├── 02-correct/
│ │ │ └── main.go
│ │ ├── 03-numeric-conversion/
│ │ │ └── main.go
│ │ ├── exercises/
│ │ │ ├── 01-convert-and-fix/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 02-convert-and-fix-2/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 03-convert-and-fix-3/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 04-convert-and-fix-4/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 05-convert-and-fix-5/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ └── README.md
│ │ └── questions/
│ │ └── questions.md
│ └── 06-project-greeter/
│ ├── 01-demonstration/
│ │ └── main.go
│ ├── 02-version1/
│ │ └── main.go
│ ├── 03-version2/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-count-arguments/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-print-the-path/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-print-your-name/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-greet-more-people/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-greet-5-people/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── README.md
│ │ └── solution-to-the-lecture-exercise/
│ │ └── main.go
│ └── questions/
│ └── questions.md
├── 07-printf/
│ ├── 01-intro/
│ │ ├── 01-println-vs-printf/
│ │ │ └── main.go
│ │ └── 02/
│ │ └── main.go
│ ├── 02-escape-sequences/
│ │ └── main.go
│ ├── 03-printing-types/
│ │ └── main.go
│ ├── 04-coding/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-print-your-age/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-print-your-name-and-lastname/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-false-claims/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-print-the-temperature/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-double-quotes/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 06-print-the-type/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 07-print-the-type-2/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 08-print-the-type-3/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 09-print-the-type-4/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 10-print-your-fullname/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ └── questions.md
├── 08-numbers-and-strings/
│ ├── 01-numbers/
│ │ ├── 01-arithmetic-operators/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ ├── 02/
│ │ │ │ └── main.go
│ │ │ └── 03-float-inaccuracy/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ ├── 02/
│ │ │ │ └── main.go
│ │ │ └── 03/
│ │ │ └── main.go
│ │ ├── 02-arithmetic-operators-examples/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ └── 02/
│ │ │ └── main.go
│ │ ├── 03-precedence/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ ├── 02/
│ │ │ │ └── main.go
│ │ │ ├── 03/
│ │ │ │ └── main.go
│ │ │ └── 04/
│ │ │ └── main.go
│ │ ├── 04-incdec-statement/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ ├── 02/
│ │ │ │ └── main.go
│ │ │ └── 03/
│ │ │ └── main.go
│ │ ├── 05-assignment-operations/
│ │ │ └── main.go
│ │ ├── 06-project-feet-to-meters/
│ │ │ ├── exercise-solution/
│ │ │ │ └── main.go
│ │ │ └── main.go
│ │ ├── exercises/
│ │ │ ├── 01-do-some-calculations/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 02-fix-the-float/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 03-precedence/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 04-incdecs/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 05-manipulate-a-counter/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 06-simplify-the-assignments/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 07-circle-area/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 08-sphere-area/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 09-sphere-volume/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ └── README.md
│ │ └── questions/
│ │ ├── 01-arithmetic-operators.md
│ │ ├── 02-precedence.md
│ │ └── 03-assignment-operations.md
│ └── 02-strings/
│ ├── 01-raw-string-literal/
│ │ └── main.go
│ ├── 02-concatenation/
│ │ ├── 01/
│ │ │ └── main.go
│ │ ├── 02-assignment-operation/
│ │ │ └── main.go
│ │ └── 03-concat-non-strings/
│ │ └── main.go
│ ├── 03-string-length/
│ │ ├── 01-len/
│ │ │ └── main.go
│ │ └── 02-unicode-len/
│ │ └── main.go
│ ├── 04-project-banger/
│ │ ├── exercise-solution/
│ │ │ └── main.go
│ │ └── main.go
│ ├── README.md
│ ├── exercises/
│ │ ├── 01-windows-path/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-print-json/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-raw-concat/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-count-the-chars/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-improved-banger/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 06-tolowercase/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 07-trim-it/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── 08-right-trim-it/
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ └── questions/
│ └── questions.md
├── 09-go-type-system/
│ ├── 01-bits/
│ │ └── main.go
│ ├── 02-bytes/
│ │ └── main.go
│ ├── 03-predeclared-types/
│ │ └── main.go
│ ├── 04-overflow/
│ │ ├── 01-problem/
│ │ │ └── main.go
│ │ ├── 02-explain/
│ │ │ └── main.go
│ │ └── 03-destructive/
│ │ └── main.go
│ ├── 05-defined-types/
│ │ ├── 01-duration-example/
│ │ │ └── main.go
│ │ ├── 02-type-definition-create-your-own-type/
│ │ │ └── main.go
│ │ └── 03-underlying-types/
│ │ ├── main.go
│ │ └── weights/
│ │ └── weights.go
│ ├── 06-aliased-types/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-optimal-types/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-the-type-problem/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-parse-arg-numbers/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-time-multiplier/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-refactor-feet-to-meter/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 06-convert-the-types/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ ├── 01-questions-predeclared-types.md
│ └── 02-questions-defined-types.md
├── 10-constants/
│ ├── 01-declarations/
│ │ ├── 01-syntax/
│ │ │ ├── 01-magic-numbers/
│ │ │ │ └── main.go
│ │ │ ├── 02-constants/
│ │ │ │ └── main.go
│ │ │ ├── 03-safety/
│ │ │ │ └── main.go
│ │ │ └── 04-rules/
│ │ │ ├── 01-immutability/
│ │ │ │ └── main.go
│ │ │ ├── 02-runtime-func/
│ │ │ │ └── main.go
│ │ │ ├── 03-runtime-var/
│ │ │ │ └── main.go
│ │ │ └── 04-len/
│ │ │ └── main.go
│ │ ├── 02-constant-types-and-expressions/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ ├── 02/
│ │ │ │ └── main.go
│ │ │ └── 03/
│ │ │ └── main.go
│ │ └── 03-multiple-declaration/
│ │ ├── 01/
│ │ │ └── main.go
│ │ ├── 02/
│ │ │ └── main.go
│ │ └── 03/
│ │ └── main.go
│ ├── 02-typeless-constants/
│ │ ├── 01-typeless-constants/
│ │ │ └── main.go
│ │ ├── 02-typed-vs-typeless/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ ├── 02/
│ │ │ │ └── main.go
│ │ │ ├── 03/
│ │ │ │ └── main.go
│ │ │ └── 04/
│ │ │ └── main.go
│ │ ├── 03-default-type/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ ├── 02/
│ │ │ │ └── main.go
│ │ │ ├── 03/
│ │ │ │ └── main.go
│ │ │ ├── 04/
│ │ │ │ └── main.go
│ │ │ └── 05/
│ │ │ └── main.go
│ │ └── 04-demo/
│ │ ├── 01/
│ │ │ └── main.go
│ │ └── 02/
│ │ └── main.go
│ ├── 03-refactor-feet-to-meters/
│ │ ├── main.go
│ │ └── solution/
│ │ ├── main.go
│ │ └── without-comments/
│ │ └── main.go
│ ├── 04-iota/
│ │ ├── 01-manually/
│ │ │ └── main.go
│ │ ├── 02-with-iota/
│ │ │ └── main.go
│ │ ├── 03-expressions/
│ │ │ └── main.go
│ │ └── 04-blank-identifier/
│ │ ├── 01/
│ │ │ └── main.go
│ │ ├── 02/
│ │ │ └── main.go
│ │ └── 03/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-minutes-in-weeks/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-remove-the-magic/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-constant-length/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-tau/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-area/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 06-no-conversions-allowed/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 07-iota-months/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 08-iota-months-2/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 09-iota-seasons/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ └── questions.md
├── 11-if/
│ ├── 01-boolean-operators/
│ │ ├── 01-comparison-operators/
│ │ │ └── main.go
│ │ ├── 02-comparison-and-assignability/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ ├── 02/
│ │ │ │ └── main.go
│ │ │ └── 03/
│ │ │ └── main.go
│ │ └── 03-logical-operators/
│ │ ├── 01-and-operator/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ └── 02/
│ │ │ └── main.go
│ │ ├── 02-or-operator/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ └── 02/
│ │ │ └── main.go
│ │ └── 03-not-operator/
│ │ ├── 01/
│ │ │ └── main.go
│ │ └── 02/
│ │ └── main.go
│ ├── 02-if-statement/
│ │ ├── 01-if-branch/
│ │ │ └── main.go
│ │ ├── 02-else-branch/
│ │ │ └── main.go
│ │ ├── 03-else-if-branch/
│ │ │ ├── 01/
│ │ │ │ └── main.go
│ │ │ └── 02/
│ │ │ └── main.go
│ │ ├── 04-refactor-feet-to-meters/
│ │ │ └── main.go
│ │ └── 05-challenge-userpass/
│ │ ├── 01-1st-challenge/
│ │ │ ├── 01-challenge/
│ │ │ │ └── main.go
│ │ │ ├── 02-solution/
│ │ │ │ └── main.go
│ │ │ └── 03-solution-refactor/
│ │ │ └── main.go
│ │ └── 02-2nd-challenge/
│ │ ├── 01-challenge/
│ │ │ └── main.go
│ │ └── 02-solution/
│ │ └── main.go
│ ├── 03-error-handling/
│ │ ├── 01-itoa/
│ │ │ └── main.go
│ │ ├── 02-atoi/
│ │ │ └── main.go
│ │ ├── 03-atoi-error-handling/
│ │ │ └── main.go
│ │ └── 04-challenge-feet-to-meters/
│ │ ├── 01-challenge/
│ │ │ └── main.go
│ │ └── 02-solution/
│ │ └── main.go
│ ├── 04-short-if/
│ │ ├── 01-without-short-if/
│ │ │ └── main.go
│ │ ├── 02-with-short-if/
│ │ │ └── main.go
│ │ ├── 03-scope/
│ │ │ └── main.go
│ │ └── 04-scope-shadowing/
│ │ ├── 01-shadowing/
│ │ │ └── main.go
│ │ └── 02-shadowing-solution/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-age-seasons/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-simplify-it/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-arg-count/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-vowel-or-cons/
│ │ │ ├── main.go
│ │ │ ├── solution/
│ │ │ │ └── main.go
│ │ │ └── solution2/
│ │ │ └── main.go
│ │ ├── 05-movie-ratings/
│ │ │ ├── main.go
│ │ │ ├── solution/
│ │ │ │ └── main.go
│ │ │ └── solution2/
│ │ │ └── main.go
│ │ ├── 06-odd-even/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 07-leap-year/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 08-simplify-leap-year/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 09-days-in-month/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ ├── 1-comparison-operators.md
│ ├── 2-logical-operators.md
│ ├── 3-if.md
│ ├── 4-error-handling.md
│ └── 5-short-if.md
├── 12-switch/
│ ├── 01-one-case/
│ │ └── main.go
│ ├── 02-multiple-cases/
│ │ └── main.go
│ ├── 03-default-clause/
│ │ └── main.go
│ ├── 04-multiple-conditions/
│ │ └── main.go
│ ├── 05-bool-expressions/
│ │ └── main.go
│ ├── 06-fallthrough/
│ │ ├── 01-without/
│ │ │ └── main.go
│ │ └── 02-with/
│ │ └── main.go
│ ├── 07-short-switch/
│ │ └── main.go
│ ├── 08-parts-of-the-day/
│ │ └── main.go
│ ├── 09-when-to-use/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-richter-scale/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-richter-scale-2/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-convert/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-string-manipulator/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-days-in-month/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ └── questions.md
├── 13-loops/
│ ├── 01-basics/
│ │ └── main.go
│ ├── 02-break/
│ │ └── main.go
│ ├── 03-continue/
│ │ ├── 01-a-before/
│ │ │ └── main.go
│ │ └── 01-b-after/
│ │ └── main.go
│ ├── 04-nested-loops-multiplication-table/
│ │ └── main.go
│ ├── 05-for-range/
│ │ ├── 01-loop-over-slices/
│ │ │ └── main.go
│ │ └── 02-loop-over-words/
│ │ └── main.go
│ ├── 06-project-lucky-number-game/
│ │ ├── 01-randomization/
│ │ │ └── main.go
│ │ └── 02-game/
│ │ └── main.go
│ ├── 07-project-word-finder/
│ │ └── main.go
│ ├── 08-word-finder-labeled-break/
│ │ └── main.go
│ ├── 09-word-finder-labeled-continue/
│ │ └── main.go
│ ├── 10-word-finder-labeled-switch/
│ │ └── main.go
│ ├── 11-goto/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-basics.md
│ │ ├── 01-sum-the-numbers/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-multiplication-table.md
│ │ ├── 02-sum-the-numbers-verbose/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-lucky-number.md
│ │ ├── 03-sum-up-to-n/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-only-evens/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-word-finder.md
│ │ ├── 05-break-up/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-crunch-the-primes.md
│ │ ├── 06-infinite-kill/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 07-multiplication-table-exercises/
│ │ │ ├── 01-dynamic-table/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ └── 02-math-tables/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 08-lucky-number-exercises/
│ │ │ ├── 01-first-turn-winner/
│ │ │ │ ├── main.go
│ │ │ │ ├── solution/
│ │ │ │ │ └── main.go
│ │ │ │ └── solution-better/
│ │ │ │ └── main.go
│ │ │ ├── 02-random-messages/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 03-double-guesses/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 04-verbose-mode/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 05-enough-picks/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ └── 06-dynamic-difficulty/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 09-word-finder-exercises/
│ │ │ ├── 01-case-insensitive/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ └── 02-path-searcher/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 10-crunch-the-primes/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ ├── 01-loops.md
│ ├── 02-randomization.md
│ └── 03-labeled-statements.md
├── 14-arrays/
│ ├── 01-whats-an-array/
│ │ └── main.go
│ ├── 02-examples-1-hipsters-love-bookstore/
│ │ └── main.go
│ ├── 03-examples-2-hipsters-love-bookstore/
│ │ └── main.go
│ ├── 04-array-literal/
│ │ └── main.go
│ ├── 05-examples-3-hipsters-love-bookstore/
│ │ └── main.go
│ ├── 06-challenge-moodly/
│ │ ├── challenge/
│ │ │ └── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 07-compare/
│ │ └── main.go
│ ├── 08-assignment/
│ │ ├── 01/
│ │ │ └── main.go
│ │ └── 02-example/
│ │ └── main.go
│ ├── 09-multi-dimensional/
│ │ └── main.go
│ ├── 10-challenge-moodly-2/
│ │ ├── challenge/
│ │ │ └── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 11-keyed-elements/
│ │ ├── 01-unkeyed/
│ │ │ └── main.go
│ │ ├── 02-keyed/
│ │ │ └── main.go
│ │ ├── 03-keyed-order/
│ │ │ └── main.go
│ │ ├── 04-keyed-auto-initialize/
│ │ │ └── main.go
│ │ ├── 05-keyed-auto-initialize-ellipsis/
│ │ │ └── main.go
│ │ ├── 06-keyed-and-unkeyed/
│ │ │ └── main.go
│ │ └── 07-xratio-example/
│ │ ├── 01-without-keys/
│ │ │ └── main.go
│ │ └── 02-with-keys/
│ │ └── main.go
│ ├── 12-compare-unnamed/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-declare-empty/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-get-set-arrays/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-array-literal/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-ellipsis/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-fix/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 06-compare/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 07-assign/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 08-wizard-printer/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 09-currency-converter/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 10-hipsters-love-search/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 11-average/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 12-sorter/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 13-word-finder/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ ├── 1-array-basics.md
│ ├── 2-arrays.md
│ └── README.md
├── 15-project-retro-led-clock/
│ ├── 01-printing-the-digits/
│ │ ├── README.md
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 02-printing-the-clock/
│ │ ├── README.md
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 03-animating-the-clock/
│ │ ├── README.md
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 04-blinking-the-separators/
│ │ ├── README.md
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 05-full-annotated-solution/
│ │ └── main.go
│ ├── README.md
│ └── exercises/
│ ├── 01-refactor/
│ │ ├── main.go
│ │ └── solution/
│ │ ├── main.go
│ │ └── placeholders.go
│ ├── 02-alarm/
│ │ ├── main.go
│ │ ├── placeholders.go
│ │ └── solution/
│ │ ├── main.go
│ │ └── placeholders.go
│ ├── 03-split-second/
│ │ ├── main.go
│ │ ├── placeholders.go
│ │ └── solution/
│ │ ├── main.go
│ │ └── placeholders.go
│ ├── 04-ticker/
│ │ ├── main.go
│ │ ├── placeholders.go
│ │ └── solution/
│ │ ├── main.go
│ │ └── placeholders.go
│ └── README.md
├── 16-slices/
│ ├── 01-slices-vs-arrays/
│ │ └── main.go
│ ├── 02-slices-vs-arrays/
│ │ └── main.go
│ ├── 03-slices-vs-arrays-examples/
│ │ └── main.go
│ ├── 04-slices-vs-arrays-unique-nums/
│ │ ├── 01-with-arrays/
│ │ │ └── main.go
│ │ └── 02-with-slices/
│ │ └── main.go
│ ├── 05-append/
│ │ ├── 1-theory/
│ │ │ └── main.go
│ │ └── 2-example/
│ │ └── main.go
│ ├── 06-slice-expressions/
│ │ ├── 1-theory/
│ │ │ └── main.go
│ │ └── 2-example/
│ │ └── main.go
│ ├── 07-slice-expressions-pagination/
│ │ └── main.go
│ ├── 08-slice-internals-1-backing-array/
│ │ ├── 1-theory/
│ │ │ └── main.go
│ │ └── 2-example/
│ │ └── main.go
│ ├── 09-slice-internals-2-slice-header/
│ │ ├── 1-theory/
│ │ │ └── main.go
│ │ └── 2-example/
│ │ └── main.go
│ ├── 10-slice-internals-3-len-cap/
│ │ ├── 1-theory/
│ │ │ └── main.go
│ │ └── 2-example/
│ │ └── main.go
│ ├── 11-slice-internals-4-append/
│ │ ├── 1-theory/
│ │ │ └── main.go
│ │ ├── 2-example/
│ │ │ └── main.go
│ │ ├── 3-example-growth/
│ │ │ └── main.go
│ │ └── 4-example-growth/
│ │ └── main.go
│ ├── 12-full-slice-expressions/
│ │ ├── 1-theory/
│ │ │ └── main.go
│ │ └── 2-example/
│ │ └── main.go
│ ├── 13-make/
│ │ ├── 1-theory/
│ │ │ └── main.go
│ │ └── 2-example/
│ │ └── main.go
│ ├── 14-copy/
│ │ ├── 01-usage/
│ │ │ └── main.go
│ │ └── 02-hacker-incident/
│ │ └── main.go
│ ├── 15-multi-dimensional-slices/
│ │ ├── version-1/
│ │ │ └── main.go
│ │ ├── version-2/
│ │ │ └── main.go
│ │ └── version-3/
│ │ └── main.go
│ ├── README.md
│ ├── exercises/
│ │ ├── 01-declare-nil/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-empty/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-slice-literal/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-declare-arrays-as-slices/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-fix-the-problems/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 06-compare-the-slices/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 07-append/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 08-append-2/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 09-append-3-fix/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 10-append-sort-nums/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 11-housing-prices/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 12-housing-prices-averages/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 13-slicing-basics/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 14-slicing-by-args/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 15-slicing-housing-prices/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 16-internals-backing-array-fix/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 17-internals-backing-array-sort/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 18-internals-slice-header/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 19-observe-len-cap/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 20-observe-the-cap-growth/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 21-correct-the-lyric/
│ │ │ ├── hints.md
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 22-adv-ops-practice/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 23-limit-the-backing-array-sharing/
│ │ │ ├── api/
│ │ │ │ └── api.go
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ ├── api/
│ │ │ │ └── api.go
│ │ │ └── main.go
│ │ ├── 24-fix-the-memory-leak/
│ │ │ ├── api/
│ │ │ │ └── api.go
│ │ │ ├── hints.md
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ ├── api/
│ │ │ │ └── api.go
│ │ │ └── main.go
│ │ ├── 25-add-lines/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 26-print-daily-requests/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ ├── 1-slices-vs-arrays.md
│ ├── 2-appending.md
│ ├── 3-slicing.md
│ ├── 4-backing-array.md
│ ├── 5-slice-header.md
│ ├── 6-capacity.md
│ ├── 7-mechanics-of-append.md
│ ├── 8-advanced-ops.md
│ └── README.md
├── 17-project-empty-file-finder/
│ ├── 01-fetch-the-files/
│ │ ├── files/
│ │ │ ├── empty1.txt
│ │ │ ├── empty2.txt
│ │ │ ├── empty3.txt
│ │ │ ├── nonEmpty1.txt
│ │ │ ├── nonEmpty2.txt
│ │ │ └── nonEmpty3.txt
│ │ └── main.go
│ ├── 02-write-to-a-file/
│ │ ├── files/
│ │ │ ├── empty1.txt
│ │ │ ├── empty2.txt
│ │ │ ├── empty3.txt
│ │ │ ├── nonEmpty1.txt
│ │ │ ├── nonEmpty2.txt
│ │ │ └── nonEmpty3.txt
│ │ └── main.go
│ ├── 03-optimize/
│ │ ├── files/
│ │ │ ├── empty1.txt
│ │ │ ├── empty2.txt
│ │ │ ├── empty3.txt
│ │ │ ├── nonEmpty1.txt
│ │ │ ├── nonEmpty2.txt
│ │ │ └── nonEmpty3.txt
│ │ └── main.go
│ └── exercises/
│ ├── 1-sort-to-a-file/
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 2-sort-to-a-file-2/
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 3-print-directories/
│ │ ├── main.go
│ │ └── solution/
│ │ ├── dir/
│ │ │ ├── .gitignore
│ │ │ ├── subdir1/
│ │ │ │ └── .gitignore
│ │ │ └── subdir2/
│ │ │ └── .gitignore
│ │ ├── dir2/
│ │ │ ├── .gitignore
│ │ │ ├── subdir1/
│ │ │ │ └── .gitignore
│ │ │ ├── subdir2/
│ │ │ │ └── .gitignore
│ │ │ └── subdir3/
│ │ │ └── .gitignore
│ │ ├── dirs.txt
│ │ └── main.go
│ └── README.md
├── 18-project-bouncing-ball/
│ ├── 01-draw-the-board/
│ │ └── main.go
│ ├── 02-add-a-buffer/
│ │ └── main.go
│ ├── 03-animate/
│ │ └── main.go
│ ├── README.md
│ └── exercises/
│ ├── 01-find-the-bug/
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 02-width-and-height/
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 03-previous-positions/
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 04-single-dimensional/
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ ├── 05-no-slice/
│ │ ├── main.go
│ │ └── solution/
│ │ └── main.go
│ └── README.md
├── 19-strings-runes-bytes/
│ ├── 01-bytes-runes-strings-basics/
│ │ └── main.go
│ ├── 02-bytes-runes-strings-charset-table/
│ │ └── main.go
│ ├── 03-bytes-runes-strings-examples/
│ │ └── main.go
│ ├── 04-rune-decoding/
│ │ ├── 01/
│ │ │ └── main.go
│ │ └── 02/
│ │ ├── benchmarks/
│ │ │ └── main.go
│ │ └── main.go
│ ├── 05-internals/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-convert/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-print-the-runes/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-rune-manipulator/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ └── README.md
├── 20-project-spam-masker/
│ ├── 01-step-1/
│ │ ├── main.go
│ │ └── spam.txt
│ ├── 02-step-2/
│ │ ├── main.go
│ │ └── spam.txt
│ ├── 03-step-2-no-append/
│ │ ├── main.go
│ │ └── spam.txt
│ └── README.md
├── 21-project-text-wrapper/
│ ├── README.md
│ ├── main.go
│ └── story.txt
├── 22-maps/
│ ├── 01-english-dict/
│ │ ├── 01-as-a-slice/
│ │ │ └── main.go
│ │ └── 02-as-a-map/
│ │ └── main.go
│ ├── 02-english-dict-map-populate/
│ │ └── main.go
│ ├── 03-internals-cloning/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-warm-up/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-populate/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-students/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ └── README.md
├── 23-input-scanning/
│ ├── 01-scanning/
│ │ ├── main.go
│ │ └── proverbs.txt
│ ├── 02-map-as-sets/
│ │ ├── main.go
│ │ └── shakespeare.txt
│ ├── 03-project-log-parser/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-uppercaser/
│ │ │ ├── main.go
│ │ │ ├── shakespeare.txt
│ │ │ └── solution/
│ │ │ ├── main.go
│ │ │ └── shakespeare.txt
│ │ ├── 02-unique-words/
│ │ │ ├── main.go
│ │ │ ├── shakespeare.txt
│ │ │ └── solution/
│ │ │ ├── main.go
│ │ │ └── shakespeare.txt
│ │ ├── 03-unique-words-2/
│ │ │ ├── main.go
│ │ │ ├── shakespeare.txt
│ │ │ └── solution/
│ │ │ ├── main.go
│ │ │ └── shakespeare.txt
│ │ ├── 04-grep/
│ │ │ ├── main.go
│ │ │ ├── shakespeare.txt
│ │ │ └── solution/
│ │ │ ├── main.go
│ │ │ └── shakespeare.txt
│ │ ├── 05-quit/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 06-log-parser/
│ │ │ ├── log.txt
│ │ │ ├── log_err_missing.txt
│ │ │ ├── log_err_negative.txt
│ │ │ ├── log_err_str.txt
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ └── README.md
├── 24-structs/
│ ├── 01-intro/
│ │ └── main.go
│ ├── 02-basics/
│ │ └── main.go
│ ├── 03-compare-assign/
│ │ └── main.go
│ ├── 04-embedding/
│ │ └── main.go
│ ├── 05-project-log-parser-structs/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ └── main.go
│ ├── 06-encoding/
│ │ └── main.go
│ ├── 07-decoding/
│ │ ├── main.go
│ │ └── users.json
│ ├── 08-decoding-2/
│ │ ├── main.go
│ │ └── users.json
│ ├── exercises/
│ │ ├── 01-warmup/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-list/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-query-by-id/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-encode/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-decode/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── questions/
│ └── README.md
├── 25-functions/
│ ├── 01-basics/
│ │ ├── bad.go
│ │ └── main.go
│ ├── 02-basics/
│ │ └── main.go
│ ├── 03-refactor-to-funcs/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ ├── main.go
│ │ └── parser.go
│ ├── 04-pass-by-value-semantics/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ ├── main.go
│ │ └── parser.go
│ ├── exercises/
│ │ ├── README.md
│ │ ├── refactor-to-funcs-1/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ ├── games.go
│ │ │ └── main.go
│ │ ├── refactor-to-funcs-2/
│ │ │ ├── games.go
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ ├── commands.go
│ │ │ ├── games.go
│ │ │ └── main.go
│ │ ├── refactor-to-funcs-3/
│ │ │ ├── commands.go
│ │ │ ├── games.go
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ ├── commands.go
│ │ │ ├── games.go
│ │ │ └── main.go
│ │ └── rewrite-log-parser-using-funcs/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ └── main.go
│ └── questions/
│ └── README.md
├── 26-pointers/
│ ├── 01-pointers/
│ │ └── main.go
│ ├── 02-pointers-basic-examples/
│ │ └── main.go
│ ├── 03-pointers-composites/
│ │ └── main.go
│ ├── 04-log-parser-pointers/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ ├── main.go
│ │ └── parser.go
│ ├── 05-log-parser-pointers-vs-values/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ ├── main.go
│ │ └── parser.go
│ ├── exercises/
│ │ ├── 01-basics/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 02-swap/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 03-fix-the-crash/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 04-simplify/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── 05-log-parser/
│ │ │ ├── log.txt
│ │ │ ├── log_err_missing.txt
│ │ │ ├── log_err_negative.txt
│ │ │ ├── log_err_str.txt
│ │ │ ├── main.go
│ │ │ └── parser.go
│ │ └── README.md
│ └── questions/
│ └── README.md
├── LICENSE
├── README.md
├── advfuncs/
│ ├── 01-variadic-funcs/
│ │ └── main.go
│ ├── 02-func-values/
│ │ └── main.go
│ ├── 03-func-to-func/
│ │ └── main.go
│ ├── 04-closures/
│ │ └── main.go
│ ├── 05-higher-order-funcs/
│ │ └── main.go
│ ├── 06-functional-programming/
│ │ └── main.go
│ ├── 07-deferred-funcs/
│ │ └── main.go
│ ├── 08-png-detector/
│ │ └── main.go
│ ├── 08-png-detector-with-panic/
│ │ └── main.go
│ ├── 10-image-detector-recover/
│ │ └── main.go
│ ├── 10b-named-params/
│ │ └── main.go
│ ├── exercises/
│ │ ├── 01-refactor/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ └── README.md
│ └── new/
│ └── 01-intro/
│ ├── funcval/
│ │ └── main.go
│ └── passfunc/
│ └── main.go
├── assets/
│ └── database.json
├── concurrency/
│ └── xxx-monte-carlo/
│ └── main.go
├── etc/
│ ├── FIX.md
│ └── stratch/
│ └── main.go
├── first/
│ ├── README.md
│ ├── explain/
│ │ ├── comments/
│ │ │ └── main.go
│ │ ├── expressions/
│ │ │ ├── 01-operator/
│ │ │ │ └── main.go
│ │ │ ├── 02-call-expression/
│ │ │ │ └── main.go
│ │ │ └── README
│ │ ├── importing/
│ │ │ ├── 01-file-scope/
│ │ │ │ └── main.go
│ │ │ └── 02-renaming/
│ │ │ └── main.go
│ │ ├── packages/
│ │ │ ├── scopes/
│ │ │ │ ├── bye.go
│ │ │ │ ├── hey.go
│ │ │ │ └── main.go
│ │ │ └── what/
│ │ │ ├── bye.go
│ │ │ ├── hey.go
│ │ │ └── main.go
│ │ ├── scopes/
│ │ │ ├── 01-scopes/
│ │ │ │ └── main.go
│ │ │ ├── 02-block-scope/
│ │ │ │ └── main.go
│ │ │ └── 03-nested-scope/
│ │ │ └── main.go
│ │ └── statements/
│ │ ├── 01-execution-flow/
│ │ │ └── main.go
│ │ └── 02-semicolons/
│ │ └── main.go
│ ├── first/
│ │ ├── exercises/
│ │ │ └── 01/
│ │ │ ├── main.go
│ │ │ └── solution/
│ │ │ └── main.go
│ │ ├── main.go
│ │ └── questions/
│ │ ├── 01-code-your-first-program-questions.md
│ │ └── 02-run-your-first-program-questions.md
│ ├── printer/
│ │ ├── cmd/
│ │ │ └── main.go
│ │ └── printer.go
│ └── printer-exercise/
│ └── solution/
│ └── golang/
│ ├── cmd/
│ │ └── main.go
│ └── go.go
├── go.mod
├── go.sum
├── interfaces/
│ ├── 01-methods/
│ │ ├── book.go
│ │ ├── game.go
│ │ └── main.go
│ ├── 02-receivers/
│ │ ├── book.go
│ │ ├── game.go
│ │ ├── huge.go
│ │ └── main.go
│ ├── 03-nonstructs/
│ │ ├── book.go
│ │ ├── game.go
│ │ ├── list.go
│ │ ├── main.go
│ │ └── money.go
│ ├── 04-interfaces/
│ │ ├── book.go
│ │ ├── game.go
│ │ ├── list.go
│ │ ├── main.go
│ │ ├── money.go
│ │ ├── power/
│ │ │ ├── blender.go
│ │ │ ├── kettle.go
│ │ │ ├── main.go
│ │ │ ├── mixer.go
│ │ │ ├── player.go
│ │ │ └── socket.go
│ │ └── puzzle.go
│ ├── 05-type-assertion/
│ │ ├── book.go
│ │ ├── game.go
│ │ ├── list.go
│ │ ├── main.go
│ │ ├── money.go
│ │ ├── puzzle.go
│ │ └── toy.go
│ ├── 06-empty-interface/
│ │ ├── book.go
│ │ ├── empty/
│ │ │ └── main.go
│ │ ├── empty2/
│ │ │ └── main.go
│ │ ├── game.go
│ │ ├── list.go
│ │ ├── main.go
│ │ ├── money.go
│ │ ├── puzzle.go
│ │ └── toy.go
│ ├── 07-type-switch/
│ │ ├── book.go
│ │ ├── game.go
│ │ ├── list.go
│ │ ├── main.go
│ │ ├── money.go
│ │ ├── puzzle.go
│ │ └── toy.go
│ ├── 08-promoted-methods/
│ │ ├── book.go
│ │ ├── game.go
│ │ ├── list.go
│ │ ├── main.go
│ │ ├── money.go
│ │ ├── product.go
│ │ ├── puzzle.go
│ │ └── toy.go
│ ├── 09-little-refactor/
│ │ ├── list.go
│ │ ├── main.go
│ │ ├── money.go
│ │ ├── product.go
│ │ └── timestamp.go
│ ├── 10-stringer/
│ │ ├── _handlemethods.go
│ │ ├── list.go
│ │ ├── main.go
│ │ ├── money.go
│ │ ├── product.go
│ │ └── timestamp.go
│ ├── 11-sort/
│ │ ├── list.go
│ │ ├── main.go
│ │ ├── money.go
│ │ ├── product.go
│ │ └── timestamp.go
│ ├── 12-marshaler/
│ │ ├── database.json
│ │ ├── list.go
│ │ ├── main.go
│ │ ├── money.go
│ │ ├── product.go
│ │ └── timestamp.go
│ ├── 13-io/
│ │ ├── alice.txt
│ │ └── main.go
│ ├── 14-io-reusable/
│ │ └── main.go
│ ├── 15-png-detector/
│ │ ├── .gitignore
│ │ └── main.go
│ ├── 16-io-compose/
│ │ ├── .gitignore
│ │ └── main.go
│ ├── 17-write-an-io-reader/
│ │ ├── .gitignore
│ │ ├── main.go
│ │ └── reader.go
│ └── 18-testing/
│ ├── .gitignore
│ ├── main.go
│ ├── reader.go
│ └── reader_test.go
├── logparser/
│ ├── functional/
│ │ ├── Makefile
│ │ ├── chartwriter.go
│ │ ├── field.go
│ │ ├── filters.go
│ │ ├── groupers.go
│ │ ├── main.go
│ │ ├── pipeline.go
│ │ ├── result.go
│ │ ├── textreader.go
│ │ └── textwriter.go
│ ├── logs/
│ │ ├── Makefile
│ │ ├── log.jsonl
│ │ ├── log.txt
│ │ ├── log_err_missing.jsonl
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.jsonl
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.jsonl
│ │ └── log_err_str.txt
│ ├── testing/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ ├── main.go
│ │ ├── main_test.go
│ │ ├── report/
│ │ │ ├── parser.go
│ │ │ ├── parser_test.go
│ │ │ ├── result.go
│ │ │ ├── summary.go
│ │ │ └── summary_test.go
│ │ └── summarize.go
│ ├── v1/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ └── main.go
│ ├── v2/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ └── main.go
│ ├── v3/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ ├── main.go
│ │ └── parser.go
│ ├── v4/
│ │ ├── log.txt
│ │ ├── log_err_missing.txt
│ │ ├── log_err_negative.txt
│ │ ├── log_err_str.txt
│ │ ├── main.go
│ │ └── parser.go
│ ├── v5/
│ │ ├── Makefile
│ │ ├── filepipe.go
│ │ ├── main.go
│ │ ├── passthrough.go
│ │ └── pipe/
│ │ ├── chartreport.go
│ │ ├── close.go
│ │ ├── filter.go
│ │ ├── filters.go
│ │ ├── group.go
│ │ ├── groupers.go
│ │ ├── jsonlog.go
│ │ ├── jsonreport.go
│ │ ├── logcount.go
│ │ ├── pipe.go
│ │ ├── pipeline.go
│ │ ├── record.go
│ │ ├── recordshare.go
│ │ ├── textlog.go
│ │ └── textreport.go
│ └── v6/
│ ├── logly/
│ │ ├── parse/
│ │ │ ├── count.go
│ │ │ ├── json.go
│ │ │ ├── parser.go
│ │ │ └── text.go
│ │ ├── record/
│ │ │ ├── json.go
│ │ │ ├── record.go
│ │ │ ├── sum.go
│ │ │ ├── text.go
│ │ │ └── validate.go
│ │ └── report/
│ │ ├── json.go
│ │ └── text.go
│ └── main.go
├── magic/
│ └── detect.go
├── magicpanic/
│ └── detect.go
├── main.go
├── translation/
│ ├── README.md
│ ├── chinese/
│ │ ├── 01-安装与介绍/
│ │ │ ├── README.md
│ │ │ ├── osx-安装指南.md
│ │ │ ├── ubuntu-安装指南.md
│ │ │ ├── windows-安装指南.md
│ │ │ └── 学习路线.md
│ │ ├── 02-编写第一个程序/
│ │ │ ├── README.md
│ │ │ ├── main.go
│ │ │ ├── 带注释的 GO 程序.md
│ │ │ ├── 练习/
│ │ │ │ ├── 01-print-names/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ └── README.md
│ │ │ └── 问题/
│ │ │ ├── 01-gopath/
│ │ │ │ └── README.md
│ │ │ ├── 02-code-your-first-program/
│ │ │ │ └── README.md
│ │ │ └── 03-run-your-first-program/
│ │ │ └── README.md
│ │ ├── 03-包和作用域/
│ │ │ ├── 01-packages/
│ │ │ │ ├── bye.go
│ │ │ │ ├── hey.go
│ │ │ │ └── main.go
│ │ │ ├── 02-scopes/
│ │ │ │ ├── 01-scopes/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 02-block-scope/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 03-nested-scope/
│ │ │ │ │ └── main.go
│ │ │ │ └── 04-package-scope/
│ │ │ │ ├── bye.go
│ │ │ │ ├── hey.go
│ │ │ │ └── main.go
│ │ │ ├── 03-importing/
│ │ │ │ ├── 01-file-scope/
│ │ │ │ │ ├── bye.go
│ │ │ │ │ └── main.go
│ │ │ │ └── 02-renaming/
│ │ │ │ └── main.go
│ │ │ ├── 练习/
│ │ │ │ ├── 01-packages/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ ├── bye.go
│ │ │ │ │ ├── greet.go
│ │ │ │ │ └── main.go
│ │ │ │ ├── 02-scopes/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── printer.go
│ │ │ │ ├── 03-importing/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ └── README.md
│ │ │ └── 问题/
│ │ │ ├── 01-packages-A/
│ │ │ │ └── README.md
│ │ │ ├── 02-packages-B/
│ │ │ │ └── README.md
│ │ │ └── 03-scopes/
│ │ │ └── README.md
│ │ ├── 04-语句-表达式-注释/
│ │ │ ├── 01-statements/
│ │ │ │ ├── 01-execution-flow/
│ │ │ │ │ └── main.go
│ │ │ │ └── 02-semicolons/
│ │ │ │ └── main.go
│ │ │ ├── 02-expressions/
│ │ │ │ ├── 01-operator/
│ │ │ │ │ └── main.go
│ │ │ │ └── 02-call-expression/
│ │ │ │ └── main.go
│ │ │ ├── 03-comments/
│ │ │ │ └── main.go
│ │ │ ├── 练习/
│ │ │ │ ├── 01-shy-semicolons/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 02-naked-expression/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 03-operators-combine/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 04-print-go-version/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 05-comment-out/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 06-use-godoc/
│ │ │ │ │ ├── exercise.md
│ │ │ │ │ └── solution/
│ │ │ │ │ └── solution.md
│ │ │ │ └── README.md
│ │ │ └── 问题/
│ │ │ ├── 01-statements/
│ │ │ │ └── README.md
│ │ │ ├── 02-expressions/
│ │ │ │ └── README.md
│ │ │ └── 03-comments/
│ │ │ └── README.md
│ │ ├── 05-编写你的第一个库程序包/
│ │ │ ├── printer/
│ │ │ │ ├── cmd/
│ │ │ │ │ └── main.go
│ │ │ │ └── printer.go
│ │ │ ├── 练习/
│ │ │ │ ├── README.md
│ │ │ │ └── solution/
│ │ │ │ └── golang/
│ │ │ │ ├── cmd/
│ │ │ │ │ └── main.go
│ │ │ │ └── go.go
│ │ │ └── 问题/
│ │ │ └── README.md
│ │ ├── 06-变量/
│ │ │ ├── 01-基础数据类型/
│ │ │ │ ├── main.go
│ │ │ │ ├── 练习/
│ │ │ │ │ ├── 01-print-the-literals/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 02-print-hexes/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── README.md
│ │ │ │ └── 问题/
│ │ │ │ └── README.md
│ │ │ ├── 02-声明/
│ │ │ │ ├── 01-声明语法/
│ │ │ │ │ ├── 01-语法/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 02-命名规则/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── 03-声明顺序/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 02-声明示例/
│ │ │ │ │ ├── 01-int/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 02-float64/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 03-bool/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── 04-string/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 03-零值/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 04-未使用的变量和空白标识符/
│ │ │ │ │ ├── 01-未使用的变量/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── 02-空白标识符/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 05-多重声明/
│ │ │ │ │ ├── 01-多重声明/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── 02-平行声明/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 06-例子/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 练习/
│ │ │ │ │ ├── 01-int/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 02-bool/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 03-float64/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 04-string/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 05-undeclarables/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 06-with-bits/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 07-multiple/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 08-multiple-2/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 09-unused/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 10-package-variable/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 11-wrong-doer/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── README.md
│ │ │ │ └── 问题/
│ │ │ │ ├── 01-what/
│ │ │ │ │ └── README.md
│ │ │ │ ├── 02-declaration/
│ │ │ │ │ └── README.md
│ │ │ │ ├── 03-unused-variables/
│ │ │ │ │ └── README.md
│ │ │ │ └── 04-zero-values/
│ │ │ │ └── README.md
│ │ │ ├── 03-简短声明/
│ │ │ │ ├── 01-初始化以及简短声明/
│ │ │ │ │ ├── 01-初始化/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 02-简短声明/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── 03-编码示例/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 02-包作用域/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 03-多重简短声明/
│ │ │ │ │ ├── 01-声明/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 02-编码示例/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── 03-重声明/
│ │ │ │ │ ├── 01/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── 02-编码示例/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 04-简短-vs-正常/
│ │ │ │ │ ├── 01-声明/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── 02-简短声明/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 练习/
│ │ │ │ │ ├── 01-short-declare/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 02-multiple-short-declare/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 03-multiple-short-declare-2/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 04-short-with-expression/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 05-short-discard/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 06-redeclare/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── README.md
│ │ │ │ └── 问题/
│ │ │ │ └── README.md
│ │ │ ├── 04-赋值/
│ │ │ │ ├── 01-概述/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 01-赋值/
│ │ │ │ │ ├── 01-赋值/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 02-强类型/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── 03-例子/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 05-多重赋值/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 06-交换/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 07-路径/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 08-路径丢弃/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 09-路径简短声明/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 练习/
│ │ │ │ │ ├── 01-make-it-blue/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 02-vars-to-vars/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 03-assign-with-expressions/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 04-find-the-rectangle-perimeter/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 05-multi-assign/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 06-multi-assign-2/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 07-multi-short-func/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 08-swapper/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 09-swapper-2/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 10-discard-the-file/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── README.md
│ │ │ │ └── 问题/
│ │ │ │ └── README.md
│ │ │ ├── 05-类型转换/
│ │ │ │ ├── 01-破坏性的/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 02-正确的/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 03-数型转换/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 练习/
│ │ │ │ │ ├── 01-convert-and-fix/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 02-convert-and-fix-2/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 03-convert-and-fix-3/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 04-convert-and-fix-4/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ ├── 05-convert-and-fix-5/
│ │ │ │ │ │ ├── main.go
│ │ │ │ │ │ └── solution/
│ │ │ │ │ │ └── main.go
│ │ │ │ │ └── README.md
│ │ │ │ └── 问题/
│ │ │ │ └── questions.md
│ │ │ └── 06-问候员项目/
│ │ │ ├── 01-演示/
│ │ │ │ └── main.go
│ │ │ ├── 02-版本1/
│ │ │ │ └── main.go
│ │ │ ├── 03-版本2/
│ │ │ │ └── main.go
│ │ │ ├── 练习/
│ │ │ │ ├── 01-count-arguments/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 02-print-the-path/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 03-print-your-name/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 04-greet-more-people/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ ├── 05-greet-5-people/
│ │ │ │ │ ├── main.go
│ │ │ │ │ └── solution/
│ │ │ │ │ └── main.go
│ │ │ │ ├── README.md
│ │ │ │ └── solution-to-the-lecture-exercise/
│ │ │ │ └── main.go
│ │ │ └── 问题/
│ │ │ └── questions.md
│ │ └── 07-打印/
│ │ ├── 01-介绍/
│ │ │ ├── 01-println-vs-printf/
│ │ │ │ └── main.go
│ │ │ └── 02/
│ │ │ └── main.go
│ │ ├── 02-转义序列/
│ │ │ └── main.go
│ │ ├── 03-打印类型/
│ │ │ └── main.go
│ │ ├── 04-编程/
│ │ │ └── main.go
│ │ ├── 练习/
│ │ │ ├── 01-print-your-age/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 02-print-your-name-and-lastname/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 03-false-claims/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 04-print-the-temperature/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 05-double-quotes/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 06-print-the-type/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 07-print-the-type-2/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 08-print-the-type-3/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 09-print-the-type-4/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ ├── 10-print-your-fullname/
│ │ │ │ ├── main.go
│ │ │ │ └── solution/
│ │ │ │ └── main.go
│ │ │ └── README.md
│ │ └── 问题/
│ │ └── questions.md
│ └── spanish/
│ ├── 01-empecemos/
│ │ ├── README.md
│ │ ├── instalacion-osx.md
│ │ ├── instalacion-ubuntu.md
│ │ └── instalacion-windows.md
│ ├── 02-tu-primer-programa/
│ │ ├── README.md
│ │ ├── anotaciones-ejemplo-programa-go.md
│ │ ├── ejercicios/
│ │ │ ├── 01-imprimiendo-nombres/
│ │ │ │ ├── main.go
│ │ │ │ └── solucion/
│ │ │ │ └── main.go
│ │ │ ├── 02-imprimiendo-gopath/
│ │ │ │ ├── ejercicio.md
│ │ │ │ └── solucion/
│ │ │ │ └── solucion.md
│ │ │ └── README.md
│ │ └── main.go
│ ├── 03-paquetes-y-funciones/
│ │ ├── 01-paquetes/
│ │ │ ├── bye.go
│ │ │ ├── hey.go
│ │ │ └── main.go
│ │ ├── 02-funciones/
│ │ │ ├── 01-funciones/
│ │ │ │ └── main.go
│ │ │ ├── 02-bloque-de-funcion/
│ │ │ │ └── main.go
│ │ │ ├── 03-funciones-anidadas/
│ │ │ │ └── main.go
│ │ │ └── 04-funcion-del-paquete/
│ │ │ ├── bye.go
│ │ │ ├── hey.go
│ │ │ └── main.go
│ │ ├── 03-importando/
│ │ │ ├── 01-funcion-del-archivo/
│ │ │ │ ├── bye.go
│ │ │ │ └── main.go
│ │ │ └── 02-renombrando/
│ │ │ └── main.go
│ │ ├── ejercicios/
│ │ │ ├── 01-paquetes/
│ │ │ │ ├── main.go
│ │ │ │ └── solucion/
│ │ │ │ ├── bye.go
│ │ │ │ ├── greet.go
│ │ │ │ └── main.go
│ │ │ ├── 02-scopes/
│ │ │ │ ├── main.go
│ │ │ │ └── solucion/
│ │ │ │ ├── main.go
│ │ │ │ └── printer.go
│ │ │ ├── 03-importando/
│ │ │ │ ├── main.go
│ │ │ │ └── solucion/
│ │ │ │ └── main.go
│ │ │ └── README.md
│ │ └── preguntas/
│ │ ├── 01-paquetes-A/
│ │ │ └── README.md
│ │ ├── 02-paquete-B/
│ │ │ └── README.md
│ │ └── 03-funciones/
│ │ └── README.md
│ └── README.md
└── x-tba/
├── README.md
├── foundations/
│ ├── 01-print-args/
│ │ ├── 01-printf/
│ │ │ └── main.go
│ │ └── main.go
│ ├── 02-variables/
│ │ ├── 01-basics/
│ │ │ └── main.go
│ │ ├── 02-short-discard/
│ │ │ └── main.go
│ │ ├── 03-conversion/
│ │ │ └── main.go
│ │ └── types/
│ │ └── main.go
│ ├── 03-if-switch-loop/
│ │ ├── 01-for-crunch-the-primes/
│ │ │ └── main.go
│ │ ├── 02-switch-months/
│ │ │ └── main.go
│ │ ├── 03-math-table-if-switch-loop/
│ │ │ └── main.go
│ │ ├── 04-lucky-number-if-for-switch/
│ │ │ └── main.go
│ │ └── 05-path-searcher-for-range/
│ │ └── main.go
│ ├── area-of-a-circle/
│ │ └── main.go
│ ├── calc/
│ │ ├── 01-shortdecl-int-conv/
│ │ │ └── main.go
│ │ ├── 02-if/
│ │ │ └── main.go
│ │ ├── 03-floats-conv/
│ │ │ └── main.go
│ │ ├── 04-error-handling/
│ │ │ └── main.go
│ │ ├── 05-switch/
│ │ │ └── main.go
│ │ ├── 06-switch/
│ │ │ └── main.go
│ │ ├── 07/
│ │ │ └── main.go
│ │ ├── 08-funcs/
│ │ │ └── main.go
│ │ ├── 09-packages/
│ │ │ ├── calc/
│ │ │ │ └── calc.go
│ │ │ └── main.go
│ │ └── calc-scanner/
│ │ ├── calculations.txt
│ │ └── main.go
│ ├── cels-to-fahr/
│ │ └── main.go
│ ├── counter/
│ │ └── main.go
│ ├── feet-to-meters/
│ │ └── main.go
│ ├── lookup/
│ │ └── main.go
│ └── volume-of-a-sphere/
│ └── main.go
├── project-png-parser/
│ └── png-parser-project/
│ ├── 1-png-anatomy-format.md
│ ├── 2-png-anatomy-example.md
│ └── main.go
├── slicing-allocs-gotcha/
│ ├── main.go
│ └── nums/
│ └── main.go
├── swapi-api-client/
│ ├── fetch/
│ │ └── main.go
│ ├── film.go
│ ├── main.go
│ ├── request.go
│ ├── starship.go
│ └── swapi.go
├── tictactoe/
│ ├── 00-print/
│ │ └── main.go
│ ├── 01-vars/
│ │ └── main.go
│ ├── 02-short-decl/
│ │ └── main.go
│ ├── 03-consts/
│ │ └── main.go
│ ├── 04-funcs/
│ │ └── main.go
│ ├── 05-testing/
│ │ ├── board_test.go
│ │ └── main.go
│ ├── 06-if-switch/
│ │ ├── board_test.go
│ │ └── main.go
│ ├── 07-loop/
│ │ ├── board.go
│ │ ├── board_test.go
│ │ ├── main.go
│ │ └── skin.go
│ ├── 08-multi-loop/
│ │ ├── board.go
│ │ ├── board_test.go
│ │ ├── main.go
│ │ └── skin.go
│ ├── 09-slices/
│ │ ├── board.go
│ │ ├── board_test.go
│ │ ├── init.go
│ │ ├── main.go
│ │ ├── play.go
│ │ └── skin.go
│ ├── 10-arrays/
│ │ ├── board.go
│ │ ├── board_test.go
│ │ ├── init.go
│ │ ├── main.go
│ │ ├── play.go
│ │ └── skin.go
│ ├── 11-randomization/
│ │ ├── board.go
│ │ ├── board_test.go
│ │ ├── init.go
│ │ ├── main.go
│ │ ├── play.go
│ │ └── skin.go
│ ├── 12-infinite-loop/
│ │ ├── board.go
│ │ ├── board_test.go
│ │ ├── init.go
│ │ ├── main.go
│ │ ├── play.go
│ │ └── skin.go
│ ├── 13-detect-winning/
│ │ ├── board.go
│ │ ├── board_test.go
│ │ ├── ending.go
│ │ ├── init.go
│ │ ├── main.go
│ │ ├── play.go
│ │ └── skin.go
│ ├── 14-more-tests/
│ │ ├── board.go
│ │ ├── board_test.go
│ │ ├── ending.go
│ │ ├── ending_test.go
│ │ ├── init.go
│ │ ├── main.go
│ │ ├── play.go
│ │ ├── play_test.go
│ │ └── skin.go
│ ├── 15-os-args/
│ │ ├── board.go
│ │ ├── board_test.go
│ │ ├── ending.go
│ │ ├── ending_test.go
│ │ ├── init.go
│ │ ├── main.go
│ │ ├── play.go
│ │ ├── play_test.go
│ │ ├── skin.go
│ │ └── turn.go
│ └── 16-types/
│ ├── board.go
│ ├── board_test.go
│ ├── ending.go
│ ├── ending_test.go
│ ├── init.go
│ ├── main.go
│ ├── play.go
│ ├── play_test.go
│ ├── skin.go
│ └── turn.go
├── tictactoe-experiments/
│ ├── 00-without-bufio/
│ │ └── main.go
│ ├── 01-without-funcs/
│ │ └── main.go
│ ├── 02-with-funcs/
│ │ └── main.go
│ ├── 03-with-structs/
│ │ └── main.go
│ ├── 04-with-methods/
│ │ └── main.go
│ ├── 05-with-pointers/
│ │ └── main.go
│ ├── 06-refactor/
│ │ ├── game.go
│ │ ├── logger.go
│ │ ├── main.go
│ │ ├── resources.md
│ │ └── skins.go
│ └── README.md
└── wizards-structs/
├── marshal/
│ └── main.go
├── server/
│ ├── list.tmpl.html
│ ├── main.go
│ ├── store.go
│ └── templates.go
└── unmarshal/
└── main.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.DS_Store
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
.vscode/*
================================================
FILE: 01-get-started/README.md
================================================
# GO INSTALLATION GUIDES
Please select your operating system below for the detailed installation instructions:
* [OS X](osx-installation.md)
* [Windows](windows-installation.md)
* [Linux (Ubuntu)](ubuntu-installation.md)
================================================
FILE: 01-get-started/osx-installation.md
================================================
# OS X INSTALLATION CHEATSHEET
## NOTE
If you have [homebrew](https://brew.sh) installed, you can easily install Go like so:
```
# if you don't have git install it like so:
brew install git
# then install go
brew install go
# add GOBIN path to your PATH in ~/.bash_profile
export PATH=${HOME}/go/bin:$PATH
```
## 1- Install Visual Studio Code Editor
1. Install it but don't open it yet.
2. Go to: [https://code.visualstudio.com](https://code.visualstudio.com)
3. Select OS X (Mac) and start downloading
4. Uncompress the downloaded file and move it to your `~/Applications` directory.
## 2- Install Git
1. Grab and run the installer. Go to: [https://git-scm.com/downloads](https://git-scm.com/downloads)
2. Select VSCode as the default editor
## 3- Install Go
1. Go to [https://golang.org/dl](https://golang.org/dl)
2. Select OS X (Mac)
3. Start the installer
## 4- Configure VS Code
1. Open VS Code; from the extensions tab at the left, search for "go" and install it
2. Close VS Code completely and open it up again
3. Go to View menu; select **Command Palette**
1. Or just press `cmd+shift+p`
2. Type: `go install`
3. Select _"Go: Install/Update Tools"_
4. Check all the checkboxes
4. After it's done, open the **Command Palette** again
1. Type: `shell`
2. Select: _"Install 'code' command in PATH"_
1. **NOTE:** You don't have to do this if you're on Windows.
## That's all! Enjoy! 🤩
> For more tutorials: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2018 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: 01-get-started/programmers-roadmap.md
================================================
# PROGRAMMER'S ROADMAP
Hi!
If you're an experienced developer, you may want to watch only the following lectures. If you follow this roadmap, you will need to watch about 50 lectures instead of 180 lectures.
This course starts from the most basics than advances toward the end, step by step. So, the complexity of the topics increases on each level. I've intentionally designed it so to make it easy for everyone.
If you think some of the topics are easy for you, then watch the recap lectures, take the quizzes and exercises, and even skip the lectures in that section altogether, you can always come back to them later.
Enjoy!
## LECTURES
* **Write Your First Go Program**
* Please watch all the lectures.
* What is Go Doc?
* The lectures under "Write a Library Package".
* **Master the Type System of Go**
* Every Go type has a zero value
* What is a blank identifier?
* Let's declare a couple of variables!
* What is type inference?
* How to short declare multiple variables?
* Why can't you short declare a variable in the package-level?
* What is redeclaration?
* When to use a short declaration?
* Get input from command-line and learn about slices
* Learn the basics of os.Args
* Greet people using os.Args
* The lectures under "Print Formatted Output Using Printf".
* Convert Celsius to Fahrenheit
* Convert Feet to Meters
* What is a Raw String Literal?
* How to get the length of a string?
* The lectures after "What is a Predeclared Type?" and to the end of the section.
* The following lectures under "Understand Untyped Constants"
* Learn the rules of constants
* Recap: Constants
* How untyped constants work under the hood?
* What is a Default Type?
* Example: time.Duration
* What is iota?
* Naming Things: Recommendations
* **Control Flow and Error Handling**
* Watch all the lectures under "Pass Me: Create a Password-Protected Program"
* Watch all the lectures under "Understand Go's Error Handling"
* Use multiple values in case conditions
* How does the fallthrough statement work?
* Solution: Parts of a Day
* Recap: Switch Statement
* How to continue a loop? (+BONUS: Debugging)
* Create a multiplication table
* How to loop over a slice?
* For Range: Learn the easy way!
* **Projects: For Beginners**
* Please watch all the lectures.
* **Remaining Sections**
* You may watch all the remaining lectures from this point. They are intermediate to advanced level lectures.
## That's all! Enjoy! 🤩
---
# BONUS: Why should you learn Go?
**In summary:** Go is easy as Python and Javascript , and it's as fast as C/C++. It's more enjoyable to work with Go than C/C++. You can go low-level, or you can stay high-level.
## What Go is used for?
Go is used mostly by web companies: Google, Facebook, Twitter, Uber, Apple, Dropbox, Soundcloud, Medium, Mozilla Firefox, Github, Docker, Kubernetes, and Heroku.
**Go is best for:** Cross-Platform Command-line Tools, Distributed Network Applications, Cloud technologies like Microservices and Serverless, Web APIs, Database Engines, Big-Data Processing Pipelines, Embedded Development, and so on.
**Go is not best for (but doable):** Desktop Apps, Writing Operating Systems, Kernel Drivers, Game Development, etc.
## Who Designed Go?
Go designed by one of the most influential people in the industry:
* Unix: Ken Thompson
* UTF-8, Plan 9: Rob Pike
* Hotspot JVM (Java Virtual Machine): Robert Griesemer
## HOW MUCH CAN YOU EARN?
* [Go Salaries](https://www.payscale.com/research/US/Skill=Go_(Golang)_Programming_Language/Salary)
## [From Eight years of Go post](https://blog.golang.org/8years):
> Today, **every single cloud company has critical components of their cloud infrastructure implemented in Go** including Google Cloud, AWS, Microsoft Azure, Heroku, and many others. Go is a key part of cloud companies like Alibaba, Cloudflare, and Dropbox. Go is a critical part of open infrastructure including Kubernetes, Cloud Foundry, Openshift, NATS, Docker, Istio, Etcd, Consul, Juju, and many more. Companies are increasingly choosing Go, to build cloud infrastructure solutions.
## What Can You Accomplish with Go?
* [A network Driver written in Go](https://www.net.in.tum.de/fileadmin/bibtex/publications/theses/2018-ixy-go.pdf) (_only 10% penalty compared to C driver_)
* [Google gVisor](https://cloud.google.com/blog/products/gcp/open-sourcing-gvisor-a-sandboxed-container-runtime) (_Userspace kernel written in Go_)
* [Multi-platform Nintendo emulator](https://humpheh.github.io/goboy/)
* [Docker: Container system](https://github.com/moby/moby)
* [Kubernetes: Container scheduling and management](https://github.com/kubernetes/kubernetes)
* VM image deduplication utility
* Chat server
* RUM beacon collector
* Time-series database engine, a client for it, command-line tools, etc.
* Map-reduce library
* Clustered front-end-optimizing reverse proxy with on the fly content rewriting, image resizing, caching, Lua event handler execution (all multi-tenant)
* Geographically distributed reverse proxy CDN nodes
* Health management daemon with event handlers and peer to peer reporting
* Pure Go DNS server
* API backend that interfaces with MySQL
* Linux process capture/restore utility
* Reverse Proxy to mask our asset server from clients.
* HTML -> PDF converter for invoice generation.
* URL shortener like tinyurl.com and goo.gl
* SMS messaging service.
* Credit Card payment gateway
* JSON Web Token package
* On the fly image processing services
* 3d render farm/content production pipeline (pretty large project)
* Production lxc container deployment
* Automated testing management
Reference: [This Reddit post](https://www.reddit.com/r/golang/comments/5nac2b/what_have_you_used_go_for_in_your_professional/).
## CHECK OUT FOR MORE INFORMATION:
* [About Go: An Overview](https://blog.learngoprogramming.com/about-go-language-an-overview-f0bee143597c)
* [Why should you learn Go?](https://medium.com/@kevalpatel2106/why-should-you-learn-go-f607681fad65)
* [Emerging language of cloud Infrastructure](https://redmonk.com/dberkholz/2014/03/18/go-the-emerging-language-of-cloud-infrastructure/)
* [Companies using Go](https://github.com/golang/go/wiki/GoUsers)
* [Eight years of Go](https://blog.golang.org/8years)
* [Twitter: Handling Five Billion Session in a Day with Go](https://blog.twitter.com/engineering/en_us/a/2015/handling-five-billion-sessions-a-day-in-real-time.html)
* [A C++ developer looks at Go](https://www.murrayc.com/permalink/2017/06/26/a-c-developer-looks-at-go-the-programming-language-part-1-simple-features/)
> For more tutorials: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2019 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: 01-get-started/ubuntu-installation.md
================================================
# Linux Installation Cheatsheet
If you want to use snap, you can easily install Go like so:
sudo snap install go --classic
Otherwise, please follow the steps below:
## 1. Update the local packages
```bash
sudo apt-get update
```
## 2. Install git
```bash
sudo apt-get install git
```
## 3. Install Go
There are two ways:
1- From Web: Select Linux and the download will begin.
```bash
firefox https://golang.org/dl
```
2- By using snap: If you use this option, skip to the 5th step.
```bash
sudo snap install go --classic
```
## 4. Copy Go into the proper directory
1. Find out the name of the downloaded file
2. Use that filename to uncompress it
```bash
gofile="DELETE_THIS_AND_TYPE_THE_NAME_OF_THE_DOWNLOADED_FILE_HERE (without its extension)"
tar -C /usr/local -xzf ~/Downloads/$gofile
```
## 5. Add Go executables directory to your PATH
1. Add `go/bin` directory to `$PATH` to be able to run the fundamental Go commands.
```bash
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
```
2. Add "$HOME/go/bin" directory to $PATH
```bash
echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.profile
```
## Install Go Tools:
* These are very handy tools to ease the development (like goimports)
* `go get` cannot be used without installing a code versioning program like Git which we already have got it above.
* This will create `~/go` directory and will download go tools into there.
* This directory is also a place where you should put your code into.
(If you're not going to use Go Modules)
```bash
go get -v -u golang.org/x/tools/...
```
## Install VSCode (Optional)
Note: You may use another coding editor if you like. However, the course uses Visual Studio Code (VSCode).
1. Open "Ubuntu Software" application
2. Search for VSCode then click "Install"
## OPTIONAL STEP:
1. Create a hello.go file in a new directory but anywhere outside of `$GOPATH`
```bash
cat < hello.go
package main
import "fmt"
func main() {
fmt.Println("hello gopher!")
}
EOF
```
2. Run the program
```bash
go run hello.go
It should print: hello gopher!
```
> For more tutorials: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2018 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: 01-get-started/windows-installation.md
================================================
# WINDOWS INSTALLATION CHEATSHEET
## NOTE
If you have [chocolatey.org](https://chocolatey.org/) package manager, you can easily install Go like so:
```
choco install golang
```
## 1- Install Visual Studio Code Editor
1. Install it but don't open it yet.
2. Go to: [https://code.visualstudio.com](https://code.visualstudio.com)
3. Select Windows and start downloading
4. Run the installer
## 2- Install Git
1. Grab and run the installer. Go to: [https://gitforwindows.org](https://gitforwindows.org)
2. Select VSCode as the default editor
3. Enable all the checkboxes
4. Select: _"Use Git from the Windows Command Prompt"_
5. Encodings: Select: _"Checkout as is..." option._
## 3- Install Go
1. Go to [https://golang.org/dl](https://golang.org/dl)
2. Select Windows and download
3. Start the installer
## 4- Configure VS Code
1. Open VS Code; from the extensions tab at the left, search for "go" and install it
2. Close VS Code completely and open it up again
3. Go to View menu; select **Command Palette**
1. Or just press `ctrl+shift+p`
2. Type: `go install`
3. Select _"Go: Install/Update Tools"_
4. Check all the checkboxes
## 5- Using Git-Bash
* In this course I'll be using bash commands. Bash is just a command-line interface used in OS X and Linux. It's one of the most popular command-line interfaces. So, if you want to use it too, instead of using the Windows default command-line, you can use git bash that you've installed. With git bash, you can type a command in command-line as you're on OS X or Linux.
* If you don't want to use git bash, it's ok too. It depends on you. But note that, I'll be using bash commands mostly. Because it allows more advanced commands as well.
* You can also prefer to use the more powerful alternative to git bash: [Linux Subsystem for Windows](https://docs.microsoft.com/en-us/windows/wsl/install-win10)
* **So, to use git bash, follow these steps:**
1. Just search for git bash from the start bar
2. Or, if there's one, click on the icon on your desktop
3. Also, setup VS Code to use git-bash by default:
1. Open VS Code
2. Go to Command Palette
1. Type: `terminal`
2. Select: _"Terminal: Select Default Shell"_
3. And, Select: _"Git Bash"_
4. **NOTE:** Normally, you can find your files under `c:\`, however, when you're using git bash, you'll find them under `/c/` directory. It's actually the very same directory, it's just a shortcut.
## That's all! Enjoy! 🤩
> For more tutorials: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2018 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: 02-write-your-first-program/README.md
================================================
# Cheatsheet: Write your First Go Program
Hi!
For reference, you can store this cheatsheet after you take the lectures in this section.
You can also print this cheatsheet and then follow the video lectures in this section along with it.
Enjoy!
---
## COMMAND LINE COMMANDS:
* Enter into a directory: `cd directoryPath`
* **WINDOWS:**
* List files in a directory: `dir`
* **OS X & LINUXes:**
* List files in a directory: `ls`
## BUILDING & RUNNING GO PROGRAMS:
* **Build a Go program:**
* While inside a program directory, type:
* `go build main.go`
* **Run a Go program:**
* While inside a program directory, type:
* `go run main.go`
## WHERE YOU SHOULD PUT YOUR SOURCE FILES?
* In any directory you like.
## FIRST PROGRAM
### Create a directory
* Create a new directory:
* `mkdir myDirectoryName`
* Go to that directory:
* `cd myDirectoryName`
### Add the source code files
* Create a new `code main.go` file.
* This is going to the create the file in the folder, and open up it in the Visual Studio Code.
* And add the following code to it and save it.
```go
package main
import "fmt"
func main() {
fmt.Println("Hi! I want to be a Gopher!")
}
```
### Run the program
* Finally, return back to the command-line.
* Run it like this: `go run main.go`
* If you create other files and run them all, you can use this command:
* `go run .`
That's all! Enjoy!
> For more tutorials: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2018 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: 02-write-your-first-program/annotated-go-program-example.md
================================================
# Annotated Example Go Program
```go
// package main is a special package
// it allows Go to create an executable file
package main
/*
This is a multi-line comment.
import keyword makes another package available
for this .go "file".
import "fmt" lets you access fmt package's functionality
here in this file.
*/
import "fmt"
// "func main" is special.
//
// Go has to know where to start
//
// func main creates a starting point for Go
//
// After compiling the code,
// Go runtime will first run this function
func main() {
// after: import "fmt"
// Println function of "fmt" package becomes available
// Look at what it looks like by typing in the console:
// go doc -src fmt Println
// Println is just an exported function from
// "fmt" package
// Exported = First Letter is uppercase
fmt.Println("Hello Gopher!")
// Go cannot call Println function by itself.
// That's why you need to call it here.
// It only calls `func main` automatically.
// -----
// Go supports Unicode characters in string literals
// And also in source-code: KÖSTEBEK!
//
// Because: Literal ~= Source Code
}
```
> For more tutorials: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2018 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: 02-write-your-first-program/exercises/01-print-names/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print names
//
// Print your name and your best friend's name using
// Println twice
//
// EXPECTED OUTPUT
// YourName
// YourBestFriendName
//
// BONUS
// Use `go run` first.
// And after that use `go build` and run your program.
// ---------------------------------------------------------
func main() {
// ?
// ?
}
================================================
FILE: 02-write-your-first-program/exercises/01-print-names/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// go run main.go
// go build
// ./solution
func main() {
fmt.Println("Nikola")
fmt.Println("Thomas")
}
================================================
FILE: 02-write-your-first-program/exercises/README.md
================================================
1. **Print your name and your best friend's name** using Println twice. [Check out this exercise here](https://github.com/inancgumus/learngo/tree/master/02-write-your-first-program/exercises/01-print-names).
2. **Say hello to yourself.**
1. Build your program using `go build`
2. **Send it to your friend**
S/he should use be using the same operating system.
For example, if you're using Windows, then hers/his should be Windows as well.
3. **Send your program to a friend with a different operating system**
So, you should compile your program for her operating system.
**Create an OSX executable:**
`GOOS=darwin GOARCH=386 go build`
**Create a Windows executable:**
`GOOS=windows GOARCH=386 go build`
**Create a Linux executable:**
`GOOS=linux GOARCH=arm GOARM=7 go build`
**You can find the full list in here:**
https://golang.org/doc/install/source#environment
**NOTE:** If you're using the command prompt or the PowerShell, you may need to use it like this:
`cmd /c "set GOOS=darwin GOARCH=386 && go build"`
3. **Call [Print](https://golang.org/pkg/fmt/#Print) instead of [Println](https://golang.org/pkg/fmt/#Println)** to see what happens.
4. **Call [Println](https://golang.org/pkg/fmt/#Println) or [Print](https://golang.org/pkg/fmt/#Print) with multiple values** by separating them using commas.
5. **Remove the double quotes from a string literal** and see what happens.
6. **Move the package and import statement** to the bottom of the file and see what happens.
7. **[Read Go online documentation](https://golang.org/pkg)**.
1. Take a quick look at the packages and read what they do.
2. Look at their source-code by clicking on their titles.
3. You don't have to understand everything, just do it. This will warm you up for the upcoming lectures.
8. Also, **take a tour on**: https://tour.golang.org/
1. Have a quick look. Check out the language features.
2. We're going to talk all about them soon.
9. [Follow me on twitter to learn more](https://twitter.com/inancgumus).
================================================
FILE: 02-write-your-first-program/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// package main is a special package
// it allows Go to create an executable file
package main
/*
This is a multi-line comment.
import keyword makes another package available
for this .go "file".
import "fmt" lets you access fmt package's functionality
here in this file.
*/
import "fmt"
// "func main" is special.
//
// Go has to know where to start
//
// func main creates a starting point for Go
//
// After compiling the code,
// Go runtime will first run this function
func main() {
// after: import "fmt"
// Println function of "fmt" package becomes available
// Look at what it looks like by typing in the console:
// go doc -src fmt Println
// Println is just an exported function from
// "fmt" package
// Exported = First Letter is uppercase
fmt.Println("Hello Gopher!")
// Go cannot call Println function by itself.
// That's why you need to call it here.
// It only calls `func main` automatically.
// -----
// Go supports Unicode characters in string literals
// And also in source-code: KÖSTEBEK!
//
// Because: Literal ~= Source Code
// EXERCISE: Remove the comments from below --> //
// fmt.Println("Merhaba Köstebek!")
// Unnecessary note:
// "Merhaba Köstebek" means "Hello Gopher"
// in Turkish language
}
================================================
FILE: 02-write-your-first-program/questions/01-gopath/README.md
================================================
## Where should you save your Go source code?
* Anywhere on my computer
* Under $GOPATH
* Under $GOPATH/src *CORRECT*
## What does $GOPATH mean?
* It's a file for Go runtime
* Stores Go source code files and compiled packages
* It's a path for gophers to follow
## Do you need to set $GOPATH?
* Yes
* No: It's stored on my desktop
* No: It's stored under my user path *CORRECT*
## How can you print $GOPATH?
* Using `ls` command
* Using `go env GOPATH` command *CORRECT*
* Using `go environment` command
================================================
FILE: 02-write-your-first-program/questions/02-code-your-first-program/README.md
================================================
## Which keyword below that you need use to define a package?
```go
package main
func main() {
}
```
1. func
2. package *CORRECT*
3. fmt.Println
4. import
> **1:** func keyword is used to declare a new function.
>
>
> **2:** That's right! package keyword allows you to define a package for a Go file.
>
>
> **3:** It's not a keyword, it's a function of the fmt package.
>
>
> **4:** import keyword is used to import a package.
>
>
## What is the purpose of using package main in the following program?
```go
package main
func main() {
}
```
* To create a library package
* To properly exit from the program
* To create an executable Go program *CORRECT*
## What is the purpose of func main in the following program?
```go
package main
func main() {
}
```
1. It defines a package called main
2. It allows Go to start executing the program *CORRECT*
3. It prints a message to the console
> **1:** main function doesn't create a package.
>
>
> **2:** That's right. Go automatically calls the main function to execute a program.
>
>
> **3:** It doesn't print anything (at least directly).
>
>
## What is the purpose of import "fmt" in the following program?
```go
package main
import "fmt"
func main() {
fmt.Println("Hi!")
}
```
1. It prints "fmt" to the console
2. It defines a new package called "fmt"
3. It imports the `fmt` package; so you can use its functionalities *CORRECT*
> **1:** `fmt.Println` prints a message not the `import "fmt"`.
>
>
> **2:** `package` keyword does that, not the `import` keyword.
>
>
> **3:** Yes. For example, after you import the fmt package you can call its Println function to print a message to the console.
>
>
## Which keyword is used to declare a new function?
* func *CORRECT*
* package
* Println
* import
## What is a function?
1. It's like a mini-program. It's a reusable and executable block of code. *CORRECT*
2. It allows Go to execute a program.
3. It allows Go to import a package called function.
4. It prints a message to the console.
> **2:** Go looks for package main and func main to do that. A function doesn't do that on its own.
>
>
> **3:** `import` keyword does that.
>
>
> **4:** For example: `fmt.Println` does that.
>
>
## Do you have to call the main function yourself?
1. Yes, so that, I can execute my program.
2. No, Go calls the main function automatically. *CORRECT*
> **1:** No, you don't need to call the main function. Go automatically executes it.
>
>
## Do you have to call a function to execute it?
_(except the main func)_
1. Yes, so that, Go can execute that function. *CORRECT*
2. Yes, so that, Go can execute my program.
3. No, Go calls the functions automatically.
> **1:** That's right. You need to call a function yourself. Go won't execute it automatically. Go only calls the main function automatically (and some other functions which you didn't learn about yet).
>
>
> **2:** That's only the job of the `func main`. There's only one `func main`.
>
>
> **3:** Go doesn't call any function automatically except the main func (and some other functions which you didn't learn about yet). So, except the main func, you need to call the functions yourself.
>
## What does the following program print?
```go
package main
func main() {
}
```
1. It prints a message to the console
2. It's a correct program but it doesn't print anything *CORRECT*
3. It's an incorrect program
> **1:** It doesn't print a message. To do that you can use fmt.Println function.
>
>
> **2:** Yes, it's a correct program, however since it doesn't contain fmt.Println it doesn't print anything.
>
>
> **3:** It's a correct program. It uses the package keyword and it has a main function. So, this is a valid and an executable Go program.
>
>
## What does this program print?
```go
package main
func main() {
fmt.Println(Hi! I want to be a Gopher!)
}
```
* Hi! I want to be a Gopher!
* It doesn't print anything
* This program is incorrect *CORRECT*
> **1:** It doesn't pass the message to Println wrapped between double-quotes. It should be like: fmt.Println("Hi! I want to be a Gopher")
>
>
> **3:** It doesn't import "fmt" package. Also see #1.
>
>
## What does this program print?
```go
package main
import "fmt"
func main() {
fmt.Println("Hi there!")
}
```
* Hi there! *CORRECT*
* fmt
* This program is incorrect; it imports the wrong package or there isn't a function called `Println`
> **2:** import "fmt" imports the `fmt` package; so you can use its functionalities.
>
>
> **3:** Actually, this program is correct.
>
>
================================================
FILE: 02-write-your-first-program/questions/03-run-your-first-program/README.md
================================================
## What is the difference between `go build` and `go run`?
1. `go run` just compiles a program; whereas `go build` both compiles and runs it.
2. `go run` both compiles and runs a program; whereas `go build` just compiles it. *CORRECT*
> **1:** It's opposite actually.
>
>
> **2:** `go run` compiles your program and puts it in a temporary directory. Then it runs the compiled program in there.
>
>
## Go saves the compiled code in a directory. What is the name of that directory?
1. The same directory where you call `go build` *CORRECT*
2. $GOPATH/src directory
3. $GOPATH/pkg directory
4. Into a temporary directory.
> **2:** There only lives Go source-code files
>
>
> **3:** Go only puts your code there when you call `go install`.
>
>
## Which is true for runtime?
1. It happens when your program starts running on a computer *CORRECT*
2. It happens while your program is being compiled
## Which is true for the compile-time?
1. It happens when your program starts running on a computer
2. It happens while your program is being compiled *CORRECT*
## When can a Go program print a message to the console?
1. While it's being compiled.
2. While it runs (after compile-time). *CORRECT*
3. While it runs (inside the compile-time).
> **1:** In the compilation step your program cannot print a message. In that stage, it's literally dead.
>
>
> **2:** That's right. That's the only time which your program can interact with a computer and instruct it to print a message to the console.
>
>
> **3:** Running can only happen after the compile-time
>
>
================================================
FILE: 03-packages-and-scopes/01-packages/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("Bye!")
}
================================================
FILE: 03-packages-and-scopes/01-packages/hey.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hey() {
fmt.Println("Hey!")
}
================================================
FILE: 03-packages-and-scopes/01-packages/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
// You can access functions from other files
// which are in the same package
// Here, `main()` can access `bye()` and `hey()`
// It's because bye.go, hey.go and main.go
// are in the main package.
bye()
hey()
}
================================================
FILE: 03-packages-and-scopes/02-scopes/01-scopes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// file scope
import "fmt"
// package scope
const ok = true
// package scope
func main() { // block scope starts
var hello = "Hello"
// hello and ok are visible here
fmt.Println(hello, ok)
} // block scope ends
================================================
FILE: 03-packages-and-scopes/02-scopes/02-block-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func nope() { // block scope starts
// hello and ok are only visible here
const ok = true
var hello = "Hello"
_ = hello
} // block scope ends
func main() { // block scope starts
// hello and ok are not visible here
// ERROR:
// fmt.Println(hello, ok)
} // block scope ends
================================================
FILE: 03-packages-and-scopes/02-scopes/03-nested-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// I didn't talk about this in a lecture
// As a side-note, I wanted to put it here
// Please review it.
var declareMeAgain = 10
func nested() { // block scope starts
// declares the same variable
// they both can exist together
// this one only belongs to this scope
// package's variable is still intact
var declareMeAgain = 5
fmt.Println("inside nested:", declareMeAgain)
} // block scope ends
func main() { // block scope starts
fmt.Println("inside main:", declareMeAgain)
nested()
// package-level declareMeAgain isn't effected
// from the change inside the nested func
fmt.Println("inside main:", declareMeAgain)
} // block scope ends
================================================
FILE: 03-packages-and-scopes/02-scopes/04-package-scope/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("Bye!")
}
================================================
FILE: 03-packages-and-scopes/02-scopes/04-package-scope/hey.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hey() {
fmt.Println("Hey!")
}
================================================
FILE: 03-packages-and-scopes/02-scopes/04-package-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
// two files belong to the same package
// calling `bye()` of bye.go here
bye()
}
// EXERCISE: Remove the comments from the below function
// And analyze the error message
// func bye() {
// fmt.Println("Bye!")
// }
// ***** EXPLANATION *****
//
// ERROR: "bye" function "redeclared"
// in "this block"
//
// "this block" means = "main package"
//
// "redeclared" means = you're using the same name
// in the same scope again
//
// main package's scope is:
// all source-code files which are in the same main package
================================================
FILE: 03-packages-and-scopes/03-importing/01-file-scope/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Uncomment below code to see the error
// (Just remove the // characters for all 3 lines below)
// This file cannot see main.go's imported names ("fmt").
// Because the imported names belong to file scope.
// func bye() {
// fmt.Println("Bye!")
// }
================================================
FILE: 03-packages-and-scopes/03-importing/01-file-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
}
================================================
FILE: 03-packages-and-scopes/03-importing/02-renaming/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
import f "fmt"
func main() {
fmt.Println("Hello!")
f.Println("There!")
}
================================================
FILE: 03-packages-and-scopes/exercises/01-packages/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Use your own package
//
// Create a few Go files and call their functions from
// the main function.
//
// 1- Create main.go, greet.go and bye.go files
// 2- In main.go: Call greet and bye functions.
// 3- Run `main.go`
//
// HINT
// greet function should be in greet.go
// bye function should be in bye.go
//
// EXPECTED OUTPUT
// hi there
// goodbye
// ---------------------------------------------------------
func main() {
// call functions of the other files here
}
================================================
FILE: 03-packages-and-scopes/exercises/01-packages/solution/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("goodbye")
}
================================================
FILE: 03-packages-and-scopes/exercises/01-packages/solution/greet.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func greet() {
fmt.Println("hi there")
}
================================================
FILE: 03-packages-and-scopes/exercises/01-packages/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
greet()
bye()
}
================================================
FILE: 03-packages-and-scopes/exercises/02-scopes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Try the scopes
//
// 1. Create two files: main.go and printer.go
//
// 2. In printer.go:
// 1. Create a function named hello
// 2. Inside the hello function, print your name
//
// 3. In main.go:
// 1. Create the usual func main
// 2. Call your function just by using its name: hello
// 3. Create a function named bye
// 4. Inside the bye function, print "bye bye"
//
// 4. In printer.go:
// 1. Call the bye function from
// inside the hello function
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 03-packages-and-scopes/exercises/02-scopes/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// as you can see, I don't need to import a package
// and I can call `hello` function here.
//
// this is because, package-scoped names
// are shared in the same package
hello()
// but here, I can't access the fmt package without
// importing it.
//
// this is because, it's in the printer.go's file scope.
// it imports it.
// this main func can also call bye function here
// bye()
}
// printer.go can call this function
//
// this is because, bye function is in the package-scope
// of the main package now.
//
// main func can also call this.
func bye() {
fmt.Println("bye bye")
}
================================================
FILE: 03-packages-and-scopes/exercises/02-scopes/solution/printer.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hello() {
// only this file can access the imported fmt package
// when others also do so, they can also access
// their own `fmt` "name"
fmt.Println("hi! this is inanc!")
bye()
}
================================================
FILE: 03-packages-and-scopes/exercises/03-importing/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Rename imports
//
// 1- Import fmt package three times with different names
//
// 2- Print a few messages using those imports
//
// EXPECTED OUTPUT
// hello
// hey
// hi
// ---------------------------------------------------------
// ?
// ?
// ?
func main() {
// ?
// ?
// ?
}
================================================
FILE: 03-packages-and-scopes/exercises/03-importing/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
import f "fmt"
import fm "fmt"
func main() {
fmt.Println("hello")
f.Println("hey")
fm.Println("hi")
}
================================================
FILE: 03-packages-and-scopes/exercises/README.md
================================================
1. **[Use your own package](https://github.com/inancgumus/learngo/tree/master/03-packages-and-scopes/exercises/01-packages)**
Create a few Go files and call their functions from the main function.
2. **[Try the scopes](https://github.com/inancgumus/learngo/tree/master/03-packages-and-scopes/exercises/02-scopes)**
Learn the effects of scoping across packages.
3. **[Rename imports](https://github.com/inancgumus/learngo/tree/master/03-packages-and-scopes/exercises/03-importing)**
Import the same package using a different name.
================================================
FILE: 03-packages-and-scopes/questions/01-packages-A/README.md
================================================
## Where to store the source code files that belong to a package?
1. Each file should go into a different directory
2. In a single directory *CORRECT*
## Why a package clause is used in a Go source-code file?
1. It's used for importing a package
2. It's used for letting Go know that the file belongs to a package *CORRECT*
3. It's used for declaring a new function
> **1:** `import` statement does that.
>
>
> **3:** `func` statement does that.
>
>
## Where you should put the `package clause` in a Go source-code file?
1. As the first code in a Go source code file *CORRECT*
2. As the last code in a Go source code file
3. You can put it anywhere
## How many times you can use `package clause` for a single source code file?
1. Once *CORRECT*
2. None
3. Multiple times
## Which one is a correct usage of `package clause`?
1. `my package`
2. `package main`
3. `pkg main`
## Which one is correct?
1. All files belong to the same package cannot call each others' functions
2. All files belong to the same package can call each others' functions *CORRECT*
## How to run multiple Go files?
1. go run *.*go
2. go build *go
3. go run go
4. go run *.go *CORRECT*
> **4:** You can also call it like (assuming there are file1.go file2.go and file3.go in the same directory): go run file1.go file2.go file3.go
>
>
================================================
FILE: 03-packages-and-scopes/questions/02-packages-B/README.md
================================================
## Which one below is a correct package type in Go?
* Empty package
* Executable package *CORRECT*
* Transferrable package
* Librarian package
## Which package type `go run` can execute?
* Empty package
* Executable package *CORRECT*
* Transferrable package
* Library package
## Which package type that `go build` can compile?
* Empty package
* Temporary package
* Both of executable and library packages *CORRECT*
* Transferrable package
## Which one is an executable package?
* `package main` with `func main` *CORRECT*
* `package Main` with `func Main`
* `package exec` with `func exec`
## Which one is a library package?
* `main package`
* `package lib` *CORRECT*
* `func package`
* `package main` with `func main`
## Which package is used for an executable Go program?
* Empty package
* Executable package *CORRECT*
* Transferrable package
* Library package
## Which package is used for reusability and can be imported?
* Empty package
* Executable package
* Transferrable package
* Library package *CORRECT*
================================================
FILE: 03-packages-and-scopes/questions/03-scopes/README.md
================================================
## What's a scope?
* Executable block of code
* The visibility of the declared names **CORRECT**
* Determines what to run
```go
package awesome
import "fmt"
var enabled bool
func block() {
var counter int
fmt.Println(counter)
}
```
## Which name below is package scoped?
1. awesome
2. fmt
3. enabled **CORRECT**
4. counter
> **3:** That's right. `enabled` is out of any functions, so it's a package scoped name. `block()` function is also package scoped; it's out of any function too.
>
>
## Which name below is file scoped?
1. awesome
2. fmt **CORRECT**
3. enabled
4. block()
5. counter
> **2:** That's right. Imported package names are file scoped. And they can only be used within the same file.
>
>
## Which name below is in the scope of the block() func?
1. awesome
2. fmt
3. enabled
4. block()
5. counter **CORRECT**
> **5:** That's right. `counter` is declared within the `block()` func, so it's in the scope of the block func. Out of the `block()` func, other code can't see it.
>
>
## Can `block()` see `enabled` name?
1. Yes: It's in the package scope **CORRECT**
2. No: It's in the file scope
3. No: It's in the block scope of block()
> **1:** All code inside the same package can see all the other package level declared names.
>
>
## Can other files in `awesome` package see `counter` name?
1. Yes
2. No: It's in the package scope
3. No: It's in the file scope
4. No: It's in the block scope of block() **CORRECT**
> **4:** That's right. None of the other code can see the names inside the `block()` function. Only the code inside the `block()` function can see them (Only to some extent. For example: Inside the block, the code can only see the variables declared before it.)
>
>
## Can other files in `awesome` package see `fmt` name?
1. Yes
2. No: It's in the package scope
3. No: It's in the file scope **CORRECT**
4. No: It's in the block scope of block()
> **3:** Only the same file can see the imported packages, not the other files whether they're in the same package or not.
>
>
## What happens if you declare the same name in the same scope as this:
```go
package awesome
import "fmt"
// declared twice in the package scope
var enabled bool
var enabled bool
func block() {
var counter int
fmt.Println(counter)
}
```
1. The newly declared name will override the previous one.
2. I can't do that. It's already been declared at the package scope. *CORRECT*
3. I can't do that. It's already been declared at the file scope.
> **2:** That's right. You can't declare the same name in the same scope. If you could do so, then how would you access it again? Or to which one?
>
>
## What happens if you declare the same name in another scope like this:
```go
package awesome
import "fmt"
// declared at the package scope
var enabled bool
func block() {
// also declared in the block scope
var enabled bool
var counter int
fmt.Println(counter)
}
```
1. The newly declared name will override the previous one. *CORRECT*
2. I can't do that. It's already been declared at the package scope.
3. I can't do that. It's already been declared at the file scope.
> **1:** Actually, you can declare the same name in the inner scopes like this. `block()`'s scope is inside its package. This means that it can access to its package's scope (but not vice versa). So, `block()`'s scope is under its package's scope. This means that you can declare the same name again. It will override the parent scope's name. They both can be exist together. Check out the example in the course repository to find out.
>
>
================================================
FILE: 04-statements-expressions-comments/01-statements/01-execution-flow/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello!")
// Statements change the execution flow
// Especially the control flow statements like `if`
if 5 > 1 {
fmt.Println("bigger")
}
}
================================================
FILE: 04-statements-expressions-comments/01-statements/02-semicolons/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello"); fmt.Println("World!")
}
================================================
FILE: 04-statements-expressions-comments/02-expressions/01-operator/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello!" + "!")
}
================================================
FILE: 04-statements-expressions-comments/02-expressions/02-call-expression/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"runtime"
)
func main() {
// runtime.NumCPU() is a call expression
fmt.Println(runtime.NumCPU() + 1)
}
================================================
FILE: 04-statements-expressions-comments/03-comments/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// Package main makes this package an executable program
package main
import "fmt"
/*
main function
Go executes this program using this function.
There should be only one main file in the main package.
Executable programs are also called "commands".
*/
func main() {
fmt.Println("Hello Gopher!")
}
================================================
FILE: 04-statements-expressions-comments/exercises/01-shy-semicolons/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Shy Semicolons
//
// 1. Try to type your statements by separating them using
// semicolons
//
// 2. Observe how Go fixes them for you
//
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 04-statements-expressions-comments/exercises/01-shy-semicolons/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// Uncomment the line of code below; then save the file.
//
// You will see that Gofmt tool will format your code automatically.
// https://golang.org/cmd/gofmt/
//
// This is because, for Go, it doesn't matter whether
// you use semicolons between the statements or not.
//
// It adds them automatically after all.
/*
fmt.Println("inanc"); fmt.Println("lina"); fmt.Println("ebru");
*/
}
================================================
FILE: 04-statements-expressions-comments/exercises/02-naked-expression/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Naked Expression
//
// 1. Try to type just "Hello" on a line.
// 2. Do not use Println
// 3. Observe the error
//
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: 04-statements-expressions-comments/exercises/02-naked-expression/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// Uncomment the code line below to see the error.
/*
"Hello"
*/
// It will say: "evaluted but not used"
//
// Because:
// "Hello" literal returns a value but there isn't any
// statement which uses it.
//
// So:
// You can't use expressions alone without statements.
}
================================================
FILE: 04-statements-expressions-comments/exercises/03-operators-combine/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Operators combine the expressions
//
// Print the expected output below using the string
// concatenation operator.
//
// HINT
// Use + operator multiple times to create "Hello!!!?".
//
// EXPECTED OUTPUT
// "Hello!!!?"
// ---------------------------------------------------------
func main() {
// fmt.Println("Hello!" + ?)
}
================================================
FILE: 04-statements-expressions-comments/exercises/03-operators-combine/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// Operators combine multiple expressions together
// as if there's a single expression.
fmt.Println("Hello!" + "!" + "!" + "?")
}
================================================
FILE: 04-statements-expressions-comments/exercises/04-print-go-version/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print the Go Version
//
// 1. Look at the runtime package documentation
// 2. Find the func that returns the Go version
// 3. Print the Go version by calling that func
//
// HINT
// It's here: https://golang.org/pkg/runtime
//
// EXPECTED OUTPUT
// "go1.10"
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: 04-statements-expressions-comments/exercises/04-print-go-version/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println(runtime.Version())
}
================================================
FILE: 04-statements-expressions-comments/exercises/05-comment-out/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Comment out
//
// Use single and multiline comments to comment Printlns.
//
// EXPECTED OUTPUT
// You shouldn't see any output after you're done.
// ---------------------------------------------------------
func main() {
fmt.Println("hello")
fmt.Println("how")
fmt.Println("are")
fmt.Println("you")
}
================================================
FILE: 04-statements-expressions-comments/exercises/05-comment-out/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// fmt.Println("hello")
/*
fmt.Println("how")
fmt.Println("are")
fmt.Println("you")
*/
}
================================================
FILE: 04-statements-expressions-comments/exercises/06-use-godoc/exercise.md
================================================
## EXERCISE
- Print the documentation of `runtime.NumCPU` function in the command line
- Print also its source code using in the command line
## HINT
You should use correct `go doc` tools
================================================
FILE: 04-statements-expressions-comments/exercises/06-use-godoc/solution/solution.md
================================================
## DOCUMENTATION:
go doc runtime NumCPU
## SOURCE CODE:
go doc -src runtime NumCPU
================================================
FILE: 04-statements-expressions-comments/exercises/README.md
================================================
1. **[Shy Semicolons](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/01-shy-semicolons)**
Observe how Go fixes semicolons for you.
2. **[Naked Expression](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/02-naked-expression)**
Observe what happens when you use an expression without a statement.
3. **[Operators Combine](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/03-operators-combine)**
Try using operators to combine expressions.
4. **[Print Go Version](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/04-print-go-version)**
Use a package from Go Standard Library to print the current version of Go on your system. Or the system which will run your program.
5. **[Comment Out](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/05-comment-out)**
Learn how to comment out.
6. **[Use the GoDoc](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/06-use-godoc)**
Try godoc yourself.
================================================
FILE: 04-statements-expressions-comments/questions/01-statements/README.md
================================================
## Which one is the correct description for a statement?
1. A statement instructs Go to do something *CORRECT*
2. A statement produces a value
3. A statement can't change the execution flow
> **2:** A statement can't produce a value. However, it can indirectly help to produce a value.
>
>
> **3:** It surely can.
>
>
## What's the direction of execution in a Go code?
1. From left to right
2. From top to bottom *CORRECT*
3. From right to left
4. From bottom to top
> **2:** That's right. Go executes the code from top-to-bottom, one statement at a time.
>
>
## Which one is the correct description for an expression?
1. An expression instructs Go to do something
2. An expression produces a value *CORRECT*
3. An expression can change the execution flow
> **1:** It can't. Only a statement can do that.
>
>
> **3:** It can't. Only a statement can do that.
>
>
## Which one is the correct description for an operator?
1. An operator instructs Go to do something
2. An operator can change the execution flow
3. An operator can combine expressions *CORRECT*
> **1:** It can't. Only a statement can do that.
>
>
> **2:** It can't. Only a statement can do that.
>
>
## Why doesn't the following program work?
```go
package main
import "fmt"
func main() {
"Hello"
}
```
1. "Hello" is an expression and it can't be on its own on a single line of code without a statement. *CORRECT*
2. By removing the double-quotes surrounding the "Hello". Like this: Hello
3. By moving "Hello" out of the func main.
## Does the following program work?
```go
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println(runtime.NumCPU()); fmt.Println("cpus"); fmt.Println("the machine")
}
```
1. It works: Expressions can be typed by separating them using semicolons
2. It doesn't work: Statements should be on their own on a single line of code
3. It works: Go adds semicolons behind the scenes for every statement already *CORRECT*
> **1:** It works but that's not the reason. And, expressions can't be typed like that.
>
>
> **2:** Are you sure?
>
>
> **3:** That's right. Whether there's a semicolon or not; Go adds them automatically. Those statements are still assumed as they're on a different code line of their own.
>
>
## Why does this program work?
```go
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println(runtime.NumCPU() + 10)
}
```
1. Operators can combine expressions *CORRECT*
2. Statements can be used with operators
3. Expressions can return multiple values
> **1:** That's right. + operator combines `runtime.NumCPU()` and `10` expressions.
>
>
> **2:** No, they can't be. For example, you can't do this: `import "fmt" + 3`. Some statement can allow expressions. However, this doesn't mean that they can be combined using expressions.
>
>
> **3:** That's right however it's irrelevant to why this code works.
>
>
================================================
FILE: 04-statements-expressions-comments/questions/02-expressions/README.md
================================================
## Please check out the questions inside the statements directory.
================================================
FILE: 04-statements-expressions-comments/questions/03-comments/README.md
================================================
## Why do you need to use comments sometimes?
1. To combine different expressions together
2. To provide explanations or generating automatic documentation for your code *CORRECT*
3. To make the code look nice and beautiful
## Which of the following code is correct?
1.
```go
package main
/ main function is an entry point /
func main() {
fmt.Println("Hi")
}
```
2. *CORRECT*
```go
package main
// main function is an entry point /*
func main() {
fmt.Println(/* this will print Hi! */ "Hi")
}
```
3.
```go
package main
/*
main function is an entry point
It allows Go to find where to start executing an executable program.
*/
func main() {
fmt.Println(// "this will print Hi!")
}
```
> **1:** `/` is not a comment. It should be `//`.
>
>
> **2:** Multiline comments can be put almost anywhere. However, when a comment starts with `/*`, it also needs to end with `*/`. Here, Go doesn't interpret `/* ... */`, it just skips it. And, when Go sees `//` as the first two characters in a code, it skips the whole line.
>
>
> **3:** `//` prevents Go to interpret the rest of the code line. That's why this code doesn't work. Go can't interpret this part because of the comment: `"this will print Hi!")`
>
>
## How should you name your code so that Go can generate documentation from your code automatically?
1. By commenting each line of the code; then it will generate the documentation from whatever it sees
2. By starting the comments using the name of the declared names *CORRECT*
3. By using multi-line comments
> **1:** This won't help. Sorry.
>
>
> **3:** It doesn't matter whether you type your comments using single-line comments or multi-line comments.
>
>
## Which tool do you need to use from the command-line to print the documentation?
1. go build
2. go run
3. go doctor
4. go doc *CORRECT*
## What's the difference between `godoc` and `go doc`?
1. `go doc` is the real tool behind `godoc`
2. `godoc` is the real tool behind `go doc` *CORRECT*
3. `go` tool is the real tool behind `go doc`
4. `go` tool is the real tool behind `godoc`
> **2:** That's right. go doc tool uses godoc tool behind the scenes. go doc is just a simplified version of the godoc tool.
>
>
================================================
FILE: 05-write-your-first-library-package/exercise/README.md
================================================
[Check out the exercise and its solution here.](https://github.com/inancgumus/learngo/tree/master/05-write-your-first-library-package/exercise)
---
# EXERCISE
1. Create a new library
2. In it, create a function that returns the Go version
3. Create a command and import your library
4. Call your function that returns Go version
5. Run your program
## HINTS
**Create your package function like this:**
```go
func Version() string {
return runtime.Version()
}
```
## EXPECTED OUTPUT
It should print the current Go version on your system.
## WARNING
You should create this package under your own folder, not in github.com/inancgumus/learngo folder. Also, please note that VS Code may automatically import my library which is in github.com/inancgumus/learngo instead of your own library.
So, if you want VS Code automatically import your own package when you save, just move github.com/inancgumus/learngo out of GOPATH to somewhere else, for example, to your Desktop (of course move it back afterward).
See [this question](https://www.udemy.com/learn-go-the-complete-bootcamp-course-golang/learn/v4/questions/5518190) in Q&A for more information.
================================================
FILE: 05-write-your-first-library-package/exercise/solution/golang/cmd/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt" // You should replace this with your username
"github.com/inancgumus/learngo/05-write-your-first-library-package/exercise/solution/golang"
)
func main() {
fmt.Println(golang.Version())
}
================================================
FILE: 05-write-your-first-library-package/exercise/solution/golang/go.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package golang
import (
"runtime"
)
// Version returns the current Go version
func Version() string {
return runtime.Version()
}
================================================
FILE: 05-write-your-first-library-package/printer/cmd/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Automatically imports!... AWESOME!
import "github.com/inancgumus/learngo/05-write-your-first-library-package/printer"
func main() {
printer.Hello()
}
================================================
FILE: 05-write-your-first-library-package/printer/printer.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package printer
import "fmt"
// Hello is an exported function
func Hello() {
fmt.Println("exported hello")
}
================================================
FILE: 05-write-your-first-library-package/questions/README.md
================================================
## Which one below is correct?
**NOTE** _There are explanations inside the answers. Even if you know the answer please try to select all of them one by one, so you can read the explanations._
1. You can run a library package.
2. In a library package, there should be a function named main (func main).
3. You can compile a library package. *CORRECT*
4. You have to compile a library package.
> **1:** You can't, but you can import it from other packages.
>
> **2:** In a library package, you don't have to include the main function. Because it isn't an executable package. Only in executable packages you need a main func.
>
> **4:** You don't have to compile it. When you import it, it will automatically be built by the other program or library when it gets compiled or ran.
## What do you need to export a name?
1. You need to type it in all capital letters
2. You need to type its first letter as a capital letter *CORRECT*
3. You need to put it inside a function scope
4. You need to create a new file for that name
> **1:** When you do so, it will be exported, that's true, but don't do that; so I assume that this answer is not correct :)
>
> **2:** That's right. Then the other packages can access it.
>
> **3:** It should be in a package scope, not function scope.
>
> **4:** You don't have to do that.
## How can you use a function from your library from an executable program?
1. You need to export your library package first; then you can access its imported names
2. You need to import your library package first; then you can access its exported names *CORRECT*
3. You can access your library package as if it's in your executable program
4. You can import it just by using its name
> **1:** You can't export packages. All packages are already exported. Unless you put them in a directory called: "internal". But, that's an advanced topic for now.
>
> **2:** That's right.
>
> **3:** You can't access a package from another package without importing it.
>
> **4:** No, you can't. You need to import it using its full directory path after GOPATH. BTW, in the near future, this may change with the Go modules support.
## In the following program, which names are exported?
```go
package wizard
import "fmt"
func doMagic() {
fmt.Println("enchanted!")
}
func Fireball() {
fmt.Println("fireball!!!")
}
```
1. fmt
2. doMagic
3. Fireball *CORRECT*
4. Println
> **1:** That's just an imported package name.
>
> **2:** It starts with a lowercase letter; so, it's not exported.
>
> **3:** That's right. It starts with a capital letter.
>
> **4:** This isn't your function. It's already been exported in the fmt package. But, it isn't exported here.
## In the following program, which names are exported?
```go
package wizard
import "fmt"
var one string
var Two string
var greenTrees string
func doMagic() {
fmt.Println("enchanted!")
}
func Fireball() {
fmt.Println("fireball!!!")
}
```
1. doMagic and Fireball
2. Fireball and Two *CORRECT*
3. Fireball, greenTrees and Two
4. Fireball, greenTrees, one and Two
> **1:** doMagic starts with a lowercase letter; so, it's not exported.
>
> **2:** That's right. Fireball and Two, they both start with a capital letter.
>
> **3:** greenTrees starts with a lowercase letter; so, it's not exported.
>
> **4:** one and greenTrees do not start with capital letters; so, they're not exported.
================================================
FILE: 06-variables/01-basic-data-types/exercises/01-print-the-literals/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print the literals
//
// 1. Print a few integer literals
//
// 2. Print a few float literals
//
// 3. Print true and false bool constants
//
// 4. Print your name using a string literal
//
// 5. Print a non-english sentence using a string literal
//
// ---------------------------------------------------------
func main() {
// Use fmt.Println()
}
================================================
FILE: 06-variables/01-basic-data-types/exercises/01-print-the-literals/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println(42, 8500, 344433, -2323)
fmt.Println(3.14, 6.28, -42.)
fmt.Println(true, false)
fmt.Println("Hi! I'm Inanc!")
fmt.Println("Merhaba, adım İnanç!")
}
================================================
FILE: 06-variables/01-basic-data-types/exercises/02-print-hexes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// THIS EXERCISE IS OPTIONAL
// ---------------------------------------------------------
// EXERCISE: Print hexes
//
// 1. Print 0 to 9 in hexadecimal
//
// 2. Print 10 to 15 in hexadecimal
//
// 3. Print 17 in hexadecimal
//
// 4. Print 25 in hexadecimal
//
// 5. Print 50 in hexadecimal
//
// 6. Print 100 in hexadecimal
//
// EXPECTED OUTPUT
// 0 1 2 3 4 5 6 7 8 9
// 10 11 12 13 14 15
// 17
// 25
// 50
// 100
//
// NOTES
// https://stackoverflow.com/questions/910309/how-to-turn-hexadecimal-into-decimal-using-brain
//
// https://simple.wikipedia.org/wiki/Hexadecimal_numeral_system
//
// ---------------------------------------------------------
func main() {
// EXAMPLES:
// I'm going to print 10 in hexadecimal
fmt.Println(0xa)
// I'm going to print 16 in hexadecimal
// 0x10
// ^^----- 1 * 0 = 0
// |
// +------ 16 * 1 = 16
// = 16
fmt.Println(0x10)
// I'm going to print 150 in hexadecimal
// 0x96
// ^^----- 1 * 6 = 6
// |
// +------ 16 * 9 = 144
// = 150
fmt.Println(0x96)
// COMMENT-OUT ALL THE CODE ABOVE, THEN,
// ADD YOUR OWN SOLUTIONS BELOW
}
================================================
FILE: 06-variables/01-basic-data-types/exercises/02-print-hexes/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println(0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9)
fmt.Println(0xa, 0xb, 0xc, 0xd, 0xe, 0xf)
fmt.Println(0x11) // 17
fmt.Println(0x19) // 25
fmt.Println(0x32) // 50
fmt.Println(0x64) // 100
}
================================================
FILE: 06-variables/01-basic-data-types/exercises/README.md
================================================
1. **[Print the literals](https://github.com/inancgumus/learngo/tree/master/06-variables/01-basic-data-types/exercises/01-print-the-literals)**
Print a few values using the literals
2. **[Print hexes](https://github.com/inancgumus/learngo/tree/master/06-variables/01-basic-data-types/exercises/02-print-hexes)** (optional exercise)
Print numbers in hexadecimal
================================================
FILE: 06-variables/01-basic-data-types/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// integer literal
fmt.Println(
-200, -100, 0, 50, 100, 100,
)
// float literal
fmt.Println(
-50.5, -20.5, -0., 1., 100.56, // ...
)
// bool constants
fmt.Println(
true, false,
)
// string literal - utf-8
fmt.Println(
"", // empty - prints just a space
"hi",
// unicode
"nasılsın?", // "how are you" in turkish
"hi there 星!", // "hi there star!"
)
}
================================================
FILE: 06-variables/01-basic-data-types/questions/README.md
================================================
## Which one below is an integer literal?
* -42 *CORRECT*
* This is an integer literal
* "Hello"
* This is a string literal
* false
* This is a bool constant
* 3.14
* This is a float literal
## Which one below is a float literal?
* -42
* "Hello"
* false
* 3.14 *CORRECT*
## Which one below is a float literal?
* 6,28
* ,28
* .28 *CORRECT*
* 628
## Which one below is a string literal?
* -42
* "Hello" *CORRECT*
* false
* 3.14
## Which one below is a bool constant?
* -42
* "Hello"
* false *CORRECT*
* 3.14
================================================
FILE: 06-variables/02-declarations/01-declaration-syntax/01-syntax/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var speed int
fmt.Println(speed)
}
================================================
FILE: 06-variables/02-declarations/01-declaration-syntax/02-naming-rules/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// VARIABLE NAMING RULES
func main() {
// CORRECT DECLARATIONS
var speed int
var SpeeD int
// underscore is allowed but not recommended
var _speed int
// Unicode letters are allowed
var 速度 int
// keep the compiler happy
_, _, _, _ = speed, SpeeD, _speed, 速度
}
================================================
FILE: 06-variables/02-declarations/01-declaration-syntax/03-order-of-declaration/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// fmt.Println(speed)
// var speed int
}
================================================
FILE: 06-variables/02-declarations/02-example-declarations/01-int/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var nFiles int
var counter int
var nCPU int
fmt.Println(
nFiles,
counter,
nCPU,
)
}
================================================
FILE: 06-variables/02-declarations/02-example-declarations/02-float64/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var heat float64
var ratio float64
var degree float64
fmt.Println(
heat,
ratio,
degree,
)
}
================================================
FILE: 06-variables/02-declarations/02-example-declarations/03-bool/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var off bool
var valid bool
var closed bool
fmt.Println(
off,
valid,
closed,
)
}
================================================
FILE: 06-variables/02-declarations/02-example-declarations/04-string/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var msg string
var name string
var text string
fmt.Println(
msg,
name,
text,
)
}
================================================
FILE: 06-variables/02-declarations/03-zero-values/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// EXERCISE: Let's run this to see the zero-values yourself
func main() {
var speed int // numeric type
var heat float64 // numeric type
var off bool
var brand string
fmt.Println(speed)
fmt.Println(heat)
fmt.Println(off)
// I've used printf to print an empty string
// EXERCISE: Use Println to see what happens
fmt.Printf("%q\n", brand)
}
================================================
FILE: 06-variables/02-declarations/04-unused-variables-and-blank-identifier/01-unused-variable/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// there's no warning for package-level vars
var packageLevelVar string
func main() {
// unused variable error
// var speed int
// if you use it, the error will be gone
// fmt.Println(speed)
}
================================================
FILE: 06-variables/02-declarations/04-unused-variables-and-blank-identifier/02-blank-identifier/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
var speed int
// let's assign the variable to the blank-identifier
// so that Go compiler won't get grumpy
_ = speed
}
================================================
FILE: 06-variables/02-declarations/05-multiple-declarations/01-multiple/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
speed int
heat float64
off bool
brand string
)
fmt.Println(speed)
fmt.Println(heat)
fmt.Println(off)
fmt.Printf("%q\n", brand)
}
================================================
FILE: 06-variables/02-declarations/05-multiple-declarations/02-parallel/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// this is equal to:
//
// var (
// speed int
// velocity int
// )
//
// or:
//
// var speed int
// var velocity int
//
var speed, velocity int
fmt.Println(speed, velocity)
}
================================================
FILE: 06-variables/02-declarations/06-examples/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// names are case-sensitive:
// MyAge, myAge, and MYAGE are different variables
// USE-CASE:
// When to use a parallel declaration?
//
// NOT GOOD:
// var myAge int
// var yourAge int
//
// SO-SO:
// var (
// myAge int
// yourAge int
// )
//
// BETTER:
var myAge, yourAge int
fmt.Println(myAge, yourAge)
var temperature float64
fmt.Println(temperature)
var success bool
fmt.Println(success)
var language string
fmt.Println(language)
}
================================================
FILE: 06-variables/02-declarations/exercises/01-int/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Declare int
//
// 1. Declare and print a variable with an int type
//
// 2. The declared variable's name should be: height
//
// EXPECTED OUTPUT
// 0
// ---------------------------------------------------------
func main() {
// var ? ?
// ?
}
================================================
FILE: 06-variables/02-declarations/exercises/01-int/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var height int
fmt.Println(height)
}
================================================
FILE: 06-variables/02-declarations/exercises/02-bool/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Declare bool
//
// 1. Declare and print a bool variable
//
// 2. The variable's name should be: isOn
//
// EXPECTED OUTPUT
// false
// ---------------------------------------------------------
func main() {
// var ? ?
// ?
}
================================================
FILE: 06-variables/02-declarations/exercises/02-bool/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var isOn bool
fmt.Println(isOn)
}
================================================
FILE: 06-variables/02-declarations/exercises/03-float64/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Declare float64
//
// 1. Declare and print a variable with a float64 type
//
// 2. The declared variable's name should be: brightness
//
// EXPECTED OUTPUT
// 0
// ---------------------------------------------------------
func main() {
// var ? ?
// ?
}
================================================
FILE: 06-variables/02-declarations/exercises/03-float64/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var brightness float64
fmt.Println(brightness)
}
================================================
FILE: 06-variables/02-declarations/exercises/04-string/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Declare string
//
// 1. Declare a string variable
//
// 2. Print that variable
//
// EXPECTED OUTPUT
// ""
// ---------------------------------------------------------
func main() {
// USE THE BELOW CODE
// You'll learn about Printf later
// var ?
// fmt.Printf("s (%T): %q\n", s, s)
// %T prints the type of the value
// %q prints an empty string
}
================================================
FILE: 06-variables/02-declarations/exercises/04-string/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var s string
fmt.Printf("s (%T): %q\n", s, s)
}
================================================
FILE: 06-variables/02-declarations/exercises/05-undeclarables/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Undeclarables
//
// 1. Declare the variables below:
// 3speed
// !speed
// spe?ed
// var
// func
// package
//
// 2. Observe the error messages
//
// NOTE
// The types of the variables are not important.
// ---------------------------------------------------------
func main() {
// var ? int
// var ? int
// var ? int
// var ? int
// var ? int
// var ? int
}
================================================
FILE: 06-variables/02-declarations/exercises/05-undeclarables/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// var 3speed int
// var !speed int
// var spe?ed int
// var var int
// var func int
// var package int
}
================================================
FILE: 06-variables/02-declarations/exercises/06-with-bits/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Declare with bits
//
// 1. Declare a few variables using the following types
// int
// int8
// int16
// int32
// int64
// float32
// float64
// complex64
// complex128
// bool
// string
// rune
// byte
//
// 2. Observe their output
//
// 3. After you've done, check out the solution
// and read the comments there
//
// EXPECTED OUTPUT
// 0 0 0 0 0 0 0 (0+0i) (0+0i) false 0 0
// ""
// ---------------------------------------------------------
func main() {
// var i int
// var i8 int8
// CONTINUE FROM HERE....
}
================================================
FILE: 06-variables/02-declarations/exercises/06-with-bits/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// integer types
var i int
var i8 int8
var i16 int16
var i32 int32
var i64 int64
// float types
var f32 float32
var f64 float64
// complex types
var c64 complex64
var c128 complex128
// bool type
var b bool
// string types
var s string
var r rune // also a numeric type
var by byte // also a numeric type
fmt.Println(
i, i8, i16, i32, i64,
f32, f64,
c64, c128,
b, r, by,
)
// You could do it with Println as well
fmt.Printf("%q\n", s)
}
================================================
FILE: 06-variables/02-declarations/exercises/07-multiple/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Multiple
//
// 1. Declare two variables using
// multiple variable declaration statement
//
// 2. The first variable's name should be active
// 3. The second variable's name should be delta
//
// 4. Print them all
//
// HINT
// You should declare a bool and an int variable
//
// EXPECTED OUTPUT
// false 0
// ---------------------------------------------------------
func main() {
// var (
// ?
// )
// fmt.Println(active, delta)
}
================================================
FILE: 06-variables/02-declarations/exercises/07-multiple/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
active bool
delta int
)
fmt.Println(active, delta)
}
================================================
FILE: 06-variables/02-declarations/exercises/08-multiple-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Multiple #2
//
// 1. Declare and initialize two string variables
// using multiple variable declaration
//
// 2. Use the type once while declaring the variables
//
// 3. The first variable's name should be firstName
// 4. The second variable's name should be lastName
//
// 5. Print them all
//
// EXPECTED OUTPUT
// "" ""
// ---------------------------------------------------------
func main() {
// ADD YOUR DECLARATION HERE
//
// REPLACE THE QUESTION-MARKS BELOW
// WITH THE NAME OF YOUR VARIABLES
// fmt.Printf("%q %q\n", ?, ?)
}
================================================
FILE: 06-variables/02-declarations/exercises/08-multiple-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var firstName, lastName string = "", ""
fmt.Printf("%q %q\n", firstName, lastName)
}
================================================
FILE: 06-variables/02-declarations/exercises/09-unused/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Unused
//
// 1. Declare a variable
//
// 2. Variable's name should be: isLiquid
//
// 3. Discard it using a blank-identifier
//
// NOTE
// Do not print the variable
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 06-variables/02-declarations/exercises/09-unused/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
var isLiquid bool
_ = isLiquid
}
================================================
FILE: 06-variables/02-declarations/exercises/10-package-variable/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Package Variable
//
// 1. Declare a variable in the package-scope
//
// 2. Observe whether something happens when you don't
// use it
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 06-variables/02-declarations/exercises/10-package-variable/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
var isLiquid bool
func main() {
}
================================================
FILE: 06-variables/02-declarations/exercises/11-wrong-doer/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Wrong doer
//
// 1. Print a variable
//
// 2. Then declare it
// (This means: Try to print it before its declaration)
//
// 3. Observe the error
// ---------------------------------------------------------
func main() {
// First print it:
// fmt.Println(?)
// Then declare it:
// var ? ?
}
================================================
FILE: 06-variables/02-declarations/exercises/11-wrong-doer/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// UNCOMMENT THE CODE BELOW TO SEE THE ERROR
// fmt.Println(age)
// var age int
}
================================================
FILE: 06-variables/02-declarations/exercises/README.md
================================================
# Declare and Print Variables
Warm up. Declare a few variables and get some experience. Get used to the variable declaration syntax.
1. **[Declare int](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/01-int)**
2. **[Declare bool](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/02-bool)**
3. **[Declare float64](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/03-float64)**
4. **[Declare string](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/04-string)**
5. **[Declare undeclarables](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/05-undeclarables)**
6. **[Declare with bits](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/06-with-bits)**
7. **[Declare multiple](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/07-multiple)**
8. **[Declare multiple 2](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/08-multiple-2)**
9. **[Declare an unused variable](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/09-unused)**
10. **[Declare a package variable](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/10-package-variable)**
11. **[Use before declare](https://github.com/inancgumus/learngo/tree/master/06-variables/02-declarations/exercises/11-wrong-doer)**
================================================
FILE: 06-variables/02-declarations/questions/01-what/README.md
================================================
# QUESTIONS: What's a variable?
## Where does a variable live?
* Hard Disk
* Computer Memory - *CORRECT*
* CPU
## What do you use a variable's name for?
* To be able to access it later - *CORRECT*
* It's just a label
* I don't need to use it
## How to change the value of a variable?
* By using its name - *CORRECT*
* By using its value
* By asking to Go
## After its declaration can you change the variable's type?
* Yes : Go is dynamically-typed
* No : Go is statically-typed - *CORRECT*
* Both: Go supports both of them
================================================
FILE: 06-variables/02-declarations/questions/02-declaration/README.md
================================================
## Which statement do you need to use for declaring variables?
* name int
* vars string name
* var name integer
* var width int *CORRECT*
## Which sentence below is correct?
* You can use a variable before declaring it
* You have to declare a variable before using it *CORRECT*
## What kind of language is Go?
* Weakly-Typed
* Dynamically-Typed
* Strongly-Typed *CORRECT*
* Freely-Typed
## Which variable name below is correct?
* int
* four *CORRECT*
* 2computers
* one?there
================================================
FILE: 06-variables/02-declarations/questions/03-unused-variables/README.md
================================================
## What happens when you don't use a declared variable in the block scope?
* Nothing, it will work fine
* It will get removed automatically
* The program won't compile *CORRECT*
## What happens when you don't use a declared variable in the package scope?
* Nothing, it will work fine *CORRECT*
* It will get removed automatically
* The program won't compile
## How can you prevent unused variable error?
* You can change the variable's name
* You can use a blank-identifier to discard it *CORRECT*
* You can change the variable's type
================================================
FILE: 06-variables/02-declarations/questions/04-zero-values/README.md
================================================
## Which type's zero value is 0?
- bool
- pointer
- string
- all numeric types *CORRECT*
## Which type's zero value is false?
- bool *CORRECT*
- pointer
- string
- all numeric types
## Which type's zero value is ""?
- bool
- pointer
- string *CORRECT*
- all numeric types
## Which type's zero value is nil?
- bool
- pointer *CORRECT*
- string
- all numeric types
================================================
FILE: 06-variables/03-short-declaration/01-initialization-and-short-declaration/01-initialization/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// = is the assignment operator
// when used within a variable declaration, it
// initializes the variable to the given value
// here, Go initializes the safe variable to true
// OPTION #1 (option #2 is better)
// var safe bool = true
// OPTION #2
var safe = true
fmt.Println(safe)
}
================================================
FILE: 06-variables/03-short-declaration/01-initialization-and-short-declaration/02-short-declaration/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// OPTION #1 (option #2 is better)
// var safe bool = true
// OPTION #2 (OK)
// var safe = true
// OPTION #3 - SHORT DECLARATION (BEST)
//
// You don't even need to type the `var` keyword
//
// Short declaration equals to:
// var safe bool = true
// var safe = true
//
// Go gets (infers) the type from the initializer value
//
// true's default type is bool
// so, the type of the safe variable becomes a bool
safe := true
fmt.Println(safe)
}
================================================
FILE: 06-variables/03-short-declaration/01-initialization-and-short-declaration/03-coding-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// var name string = "Carl"
// var name = "Carl"
name := "Carl"
// var isScientist bool = true
// var isScientist = true
isScientist := true
// var age int = 62
// var age = 62
age := 62
// var degree float64 = 5.
// var degree = 5.
degree := 5.
fmt.Println(name, isScientist, age, degree)
// type inference also works for variables
//
// Go gets the type of the variable and assigns it
// to the newly declared variable
//
// The type of the name2 variable is `string` now
name2 := name
fmt.Println(name2)
}
================================================
FILE: 06-variables/03-short-declaration/02-package-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// You can't use declaration statements without a keyword
// Short declaration doesn't have a keyword (`var`)
// So, it can't be used at the package scope
//
// SYNTAX ERROR:
// "non-declaration statement outside function body"
// safe := true
// However, you can use the normal declaration at the
// package scope. Since it has a keyword: `var`
var safe = true
func main() {
fmt.Println(safe)
}
================================================
FILE: 06-variables/03-short-declaration/03-multiple-short-declaration/01-declaration/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// the number of variables and values should be equal
// -> `true` is being assigned to `safe`
// -> `50` is being assigned to `speed`
safe, speed := true, 50
fmt.Println(safe, speed)
}
================================================
FILE: 06-variables/03-short-declaration/03-multiple-short-declaration/02-coding-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
name, lastname := "Nikola", "Tesla"
fmt.Println(name, lastname)
birth, death := 1856, 1943
fmt.Println(birth, death)
on, off := true, false
fmt.Println(on, off)
// there's no limit
// however, more declarations that you declare
// more unreadable it becomes...
degree, ratio, heat := 10.55, 30.5, 20.
fmt.Println(degree, ratio, heat)
// you can short declare variables with different types
nFiles, valid, msg := 10, true, "hello"
fmt.Println(nFiles, valid, msg)
}
================================================
FILE: 06-variables/03-short-declaration/03-multiple-short-declaration/03-redeclaration/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// `safe`'s value is `false`
var safe bool
// `safe`'s value is now `true`
// `speed` is declared and initialized to `50`
// redeclaration only works when
//
// at least one of the variables
// should be a new variable
safe, speed := true, 50
fmt.Println(safe, speed)
// EXERCISE
//
// Declare the speed variable before
// the short declaration "again"
//
// Observe what happens
}
================================================
FILE: 06-variables/03-short-declaration/03-multiple-short-declaration/03-redeclaration/02-coding-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// EXAMPLE #1
name := "Nikola"
fmt.Println(name)
// name already exists in this block
// name := "Marie"
// just assigns new values to name
// and declares the new variable age with a value of 66
name, age := "Marie", 66
fmt.Println(name, age)
// EXAMPLE #2
// name = "Albert"
// birth := 1879
// redeclaration below equals to the statements just above
//
// `name` is an existing variable
// Go just assigns "Albert" to the name variable
//
// `birth` is a new variable
// Go declares it and assigns it a value of `1879`
name, birth := "Albert", 1879
fmt.Println(name, birth)
}
================================================
FILE: 06-variables/03-short-declaration/04-short-vs-normal/01-declaration/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// normal declaration use cases
// -----------------------------------------------------
// when you need a package scoped variable
// -----------------------------------------------------
// version := 0 // YOU CAN'T
var version int
func main() {
// -----------------------------------------------------
// if you don't know the initial value
// -----------------------------------------------------
// DON'T DO THIS:
// score := 0
// DO THIS:
// var score int
// -----------------------------------------------------
// group variables for readability
// -----------------------------------------------------
// var (
// video string
// duration int
// current int
// )
}
================================================
FILE: 06-variables/03-short-declaration/04-short-vs-normal/02-short-declaration/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// short declaration use cases
func main() {
// -----------------------------------------------------
// if you know the initial value
// -----------------------------------------------------
// DON'T DO THIS:
// var width, height = 100, 50
// DO THIS (concise):
// width, height := 100, 50
// -----------------------------------------------------
// redeclaration
// -----------------------------------------------------
// DON'T DO THIS:
// width = 50
// color := red
// DO THIS (concise):
// width, color := 50, "red"
}
================================================
FILE: 06-variables/03-short-declaration/exercises/01-short-declare/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Short Declare
//
// Declare and then print four variables using
// the short declaration statement.
//
// EXPECTED OUTPUT
// i: 314 f: 3.14 s: Hello b: true
// ---------------------------------------------------------
func main() {
// ADD YOUR DECLARATIONS HERE
//
// THEN UNCOMMENT THE CODE BELOW
// fmt.Println(
// "i:", i,
// "f:", f,
// "s:", s,
// "b:", b,
// )
}
================================================
FILE: 06-variables/03-short-declaration/exercises/01-short-declare/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
i := 314
f := 3.14
s := "Hello"
b := true
fmt.Println(
"i:", i,
"f:", f,
"s:", s,
"b:", b,
)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/02-multiple-short-declare/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Multiple Short Declare
//
// Declare two variables using multiple short declaration
//
// EXPECTED OUTPUT
// 14 true
// ---------------------------------------------------------
func main() {
// ADD YOUR DECLARATIONS HERE
//
// THEN UNCOMMENT THE CODE BELOW
// fmt.Println(a, b)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/02-multiple-short-declare/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
a, b := 14, true
fmt.Println(a, b)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/03-multiple-short-declare-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Multiple Short Declare #2
//
// 1. Declare two variables using multiple short declaration
//
// 2. `a` variable's value should be 42
// 3. `c` variable's value should be "good"
//
// EXPECTED OUTPUT
// 42 good
// ---------------------------------------------------------
func main() {
// ADD YOUR DECLARATIONS HERE
//
// THEN UNCOMMENT THE CODE BELOW
// fmt.Println(a, c)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/03-multiple-short-declare-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
a, c := 42, "good"
fmt.Println(a, c)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/04-short-with-expression/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Short With Expression
//
// 1. Short declare a variable named `sum`
//
// 2. Initialize it with an expression by adding 27 and 3.5
//
// EXPECTED OUTPUT
// 30.5
// ---------------------------------------------------------
func main() {
// ADD YOUR DECLARATION HERE
//
// THEN UNCOMMENT THE CODE BELOW
// fmt.Println(sum)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/04-short-with-expression/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
sum := 27 + 3.5
fmt.Println(sum)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/05-short-discard/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Short Discard
//
// 1. Short declare two bool variables
// (use multiple short declaration syntax)
//
// 2. Initialize both variables to true
//
// 3. Change your declaration and
// discard the 2nd variable's value
// using the blank-identifier
//
// 4. Print only the 1st variable
//
// EXPECTED OUTPUT
// true
// ---------------------------------------------------------
func main() {
// ADD YOUR DECLARATIONS HERE
//
// THEN UNCOMMENT THE CODE BELOW
// fmt.Println(on)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/05-short-discard/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
// You can discard values in a short declaration
on, _ := true, true
fmt.Println(on)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/06-redeclare/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Redeclare
//
// 1. Short declare two int variables: age and yourAge
// (use multiple short declaration syntax)
//
// 2. Short declare a new float variable: ratio
// And, change the 'age' variable to 42
//
// (! You should use redeclaration)
//
// 4. Print all the variables
//
// EXPECTED OUTPUT
// 42, 20, 3.14
// ---------------------------------------------------------
func main() {
// ADD YOUR DECLARATIONS HERE
//
// THEN UNCOMMENT THE CODE BELOW
// fmt.Println(age, yourAge, ratio)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/06-redeclare/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
age, yourAge := 10, 20
age, ratio := 42, 3.14
fmt.Println(age, yourAge, ratio)
}
================================================
FILE: 06-variables/03-short-declaration/exercises/README.md
================================================
# Short Declare
Time to declare a few variables using the short declaration syntax. You'll also use the redeclaration and discarding.
1. **[Short Declare](https://github.com/inancgumus/learngo/tree/master/06-variables/03-short-declaration/exercises/01-short-declare)**
2. **[Multiple Short Declare](https://github.com/inancgumus/learngo/tree/master/06-variables/03-short-declaration/exercises/02-multiple-short-declare)**
3. **[Multiple Short Declare #2](https://github.com/inancgumus/learngo/tree/master/06-variables/03-short-declaration/exercises/03-multiple-short-declare-2)**
4. **[Short With Expression](https://github.com/inancgumus/learngo/tree/master/06-variables/03-short-declaration/exercises/04-short-with-expression)**
5. **[Short Discard](https://github.com/inancgumus/learngo/tree/master/06-variables/03-short-declaration/exercises/05-short-discard)**
6. **[Redeclare](https://github.com/inancgumus/learngo/tree/master/06-variables/03-short-declaration/exercises/06-redeclare)**
================================================
FILE: 06-variables/03-short-declaration/questions/README.md
================================================
## Which is a correct declaration?
* var int safe := 3
* var safe bool := 3
* safe := true *CORRECT*
## Which is a correct declaration?
* var short := true
* int num := 1
* speed := 50 *CORRECT*
* num int := 2
## Which is a correct declaration?
* x, y, z := 10, 20
* x = 10,
* y, x, p := 5, "hi", 1.5 *CORRECT*
* y, x = "hello", 10
## Which declaration is equal to the following declaration?
```go
var s string = "hi"
```
* var s int = "hi"
* s := "hi" *CORRECT*
* s, p := 2, 3
## Which declaration is equal to the following declaration?
```go
var n = 10
```
* n := 10.0
* m, n := 1, 0
* var n int = 10 *CORRECT*
## What's the type of the `s` variable?
```go
s := "hmm..."
```
* bool
* string *CORRECT*
* int
* float64
## What's the type of the `b` variable?
```go
b := true
```
* bool *CORRECT*
* string
* int
* float64
## What's the type of the `i` variable?
```go
i := 42
```
* bool
* string
* int *CORRECT*
* float64
## What's the type of the `f` variable?
```go
f := 6.28
```
* bool
* string
* int
* float64 *CORRECT*
## What's the value of the `x` variable?
```go
y, x := false, 20
```
* 10
* 20 *CORRECT*
* false
## What's the value of the `x` variable?
```go
y, x := false, 20
x, z := 10, "hi"
```
* 10 *CORRECT*
* 20
* false
## Which of the following declaration can be used in the package scope?
* x := 10
* y, x := 10, 5
* var x, y = 5, 10 *CORRECT*
================================================
FILE: 06-variables/04-assignment/01-assignment/01-assignment/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var speed int
fmt.Println(speed)
speed = 100
fmt.Println(speed)
speed = speed - 25
fmt.Println(speed)
}
================================================
FILE: 06-variables/04-assignment/01-assignment/02-strongly-typed/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Go is a strongly typed programming language.
// Even a float and an integer are different types.
// Or: int32 and int are different types.
// EXERCISE: Try uncommenting the lines
// And observe the errors
func main() {
var speed int
// speed = "100"
var running bool
// running = 1
var force float64
// speed = force
// Go automatically converts the typeless
// integer literal to float64 automatically
force = 1
// keep the compiler happy
_, _, _ = speed, running, force
}
================================================
FILE: 06-variables/04-assignment/01-assignment/03-examples/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
name string
age int
famous bool
)
// Example #1
name = "Newton"
age = 84
famous = true
fmt.Println(name, age, famous)
// Example #2
name = "Somebody"
age = 20
famous = false
fmt.Println(name, age, famous)
// Example #3
// EXERCISE: Why this doesn't work? Think about it.
// name = 20
// name = age
// save the previous value of the variable
// to a new variable
var prevName string
prevName = name
// overwrite the value of the original variable
// by assigning to it
name = "Einstein"
fmt.Println("previous name:", prevName)
fmt.Println("current name :", name)
}
================================================
FILE: 06-variables/04-assignment/01-overview/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var counter int
fmt.Println("counter's name : counter")
fmt.Println("counter's value:", counter)
fmt.Printf("counter's type : %T\n", counter)
counter = 10 // OK
// counter = "ten" // NOT OK
fmt.Println("counter's value:", counter)
counter++
fmt.Println("counter's value:", counter)
}
================================================
FILE: 06-variables/04-assignment/05-multiple-assignment/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
var (
speed int
now time.Time
)
speed, now = 100, time.Now()
fmt.Println(speed, now)
// EXERCISE:
// Try this alternative (formatted time).
// fmt.Println(speed, now.Format(time.Kitchen))
}
================================================
FILE: 06-variables/04-assignment/06-swapping/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
speed = 100
prevSpeed = 50
)
speed, prevSpeed = prevSpeed, speed
fmt.Println(speed, prevSpeed)
}
================================================
FILE: 06-variables/04-assignment/07-path-project/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"path"
)
func main() {
var dir, file string
dir, file = path.Split("css/main.css")
fmt.Println("dir :", dir)
fmt.Println("file:", file)
}
================================================
FILE: 06-variables/04-assignment/08-path-project-discarding/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"path"
)
func main() {
var file string
_, file = path.Split("css/main.css")
fmt.Println("file:", file)
}
================================================
FILE: 06-variables/04-assignment/09-path-project-shortdecl/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"path"
)
func main() {
_, file := path.Split("css/main.css")
// or this:
// dir, file := path.Split("css/main.css")
fmt.Println("file:", file)
}
================================================
FILE: 06-variables/04-assignment/exercises/01-make-it-blue/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Make It Blue
//
// 1. Change `color` variable's value to "blue"
//
// 2. Print it
//
// EXPECTED OUTPUT
// blue
// ---------------------------------------------------------
func main() {
// UNCOMMENT THE CODE BELOW:
// color := "green"
// ADD YOUR CODE BELOW:
// ?
}
================================================
FILE: 06-variables/04-assignment/exercises/01-make-it-blue/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
color := "green"
color = "blue"
fmt.Println(color)
}
================================================
FILE: 06-variables/04-assignment/exercises/02-vars-to-vars/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Variables To Variables
//
// 1. Change the value of `color` variable to "dark green"
//
// 2. Do not assign "dark green" to `color` directly
//
// Instead, use the `color` variable again
// while assigning to `color`
//
// 3. Print it
//
// RESTRICTIONS
// WRONG ANSWER, DO NOT DO THIS:
// `color = "dark green"`
//
// HINT
// + operator can concatenate string values
//
// Example:
//
// "h" + "e" + "y" returns "hey"
//
// EXPECTED OUTPUT
// dark green
// ---------------------------------------------------------
func main() {
// UNCOMMENT THE CODE BELOW:
// color := "green"
// ADD YOUR CODE BELOW
// ?
// UNCOMMENT THE CODE BELOW TO PRINT THE VARIABLE
// fmt.Println(color)
}
================================================
FILE: 06-variables/04-assignment/exercises/02-vars-to-vars/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
color := "green"
// `"dark " + color` is an expression
color = "dark " + color
fmt.Println(color)
}
================================================
FILE: 06-variables/04-assignment/exercises/03-assign-with-expressions/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Assign With Expressions
//
// 1. Multiply 3.14 with 2 and assign it to `n` variable
//
// 2. Print the `n` variable
//
// HINT
// Example: 3 * 2 = 6
// * is the product operator (it multiplies numbers)
//
// EXPECTED OUTPUT
// 6.28
// ---------------------------------------------------------
func main() {
// DON'T TOUCH THIS
// Declares a new float64 variable
// 0. means 0.0
n := 0.
// ADD YOUR CODE BELOW
// ?
fmt.Println(n)
}
================================================
FILE: 06-variables/04-assignment/exercises/03-assign-with-expressions/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
n := 0.
n = 3.14 * 2
fmt.Println(n)
}
================================================
FILE: 06-variables/04-assignment/exercises/04-find-the-rectangle-perimeter/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Find the Rectangle's Perimeter
//
// 1. Find the perimeter of a rectangle
// Its width is 5
// Its height is 6
//
// 2. Assign the result to the `perimeter` variable
//
// 3. Print the `perimeter` variable
//
// HINT
// Formula = 2 times the width and height
//
// EXPECTED OUTPUT
// 22
//
// BONUS
// Find more formulas here and calculate them in new programs
// https://www.mathsisfun.com/area.html
// ---------------------------------------------------------
func main() {
// UNCOMMENT THE CODE BELOW:
// var (
// perimeter int
// width, height = 5, 6
// )
// USE THE VARIABLES ABOVE WHEN CALCULATING YOUR RESULT
// ADD YOUR CODE BELOW
}
================================================
FILE: 06-variables/04-assignment/exercises/04-find-the-rectangle-perimeter/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
perimeter int
width, height = 5, 6
)
// first calculates: (width + height)
// then : multiplies it with 2
// just like in math
perimeter = 2 * (width + height)
fmt.Println(perimeter)
}
================================================
FILE: 06-variables/04-assignment/exercises/05-multi-assign/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Multi Assign
//
// 1. Assign "go" to `lang` variable
// and assign 2 to `version` variable
// using a multiple assignment statement
//
// 2. Print the variables
//
// EXPECTED OUTPUT
// go version 2
// ---------------------------------------------------------
func main() {
// DO NOT TOUCH THIS
var (
lang string
version int
)
// ADD YOUR CODE BELOW
// DO NOT TOUCH THIS
fmt.Println(lang, "version", version)
}
================================================
FILE: 06-variables/04-assignment/exercises/05-multi-assign/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
lang string
version int
)
lang, version = "go", 2
fmt.Println(lang, "version", version)
}
================================================
FILE: 06-variables/04-assignment/exercises/06-multi-assign-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Multi Assign #2
//
// 1. Assign the correct values to the variables
// to match to the EXPECTED OUTPUT below
//
// 2. Print the variables
//
// HINT
// Use multiple Println calls to print each sentence.
//
// EXPECTED OUTPUT
// Air is good on Mars
// It's true
// It is 19.5 degrees
// ---------------------------------------------------------
func main() {
// UNCOMMENT THE CODE BELOW:
// var (
// planet string
// isTrue bool
// temp float64
// )
// ADD YOUR CODE BELOW
}
================================================
FILE: 06-variables/04-assignment/exercises/06-multi-assign-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
planet string
isTrue bool
temp float64
)
planet, isTrue, temp = "Mars", true, 19.5
fmt.Println("Air is good on", planet)
fmt.Println("It's", isTrue)
fmt.Println("It is", temp, "degrees")
}
================================================
FILE: 06-variables/04-assignment/exercises/07-multi-short-func/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Multi Short Func
//
// 1. Declare two variables using multiple short declaration syntax
//
// 2. Initialize the variables using `multi` function below
//
// 3. Discard the 1st variable's value in the declaration
//
// 4. Print only the 2nd variable
//
// NOTE
// You should use `multi` function
// while initializing the variables
//
// EXPECTED OUTPUT
// 4
// ---------------------------------------------------------
func main() {
// ADD YOUR DECLARATIONS HERE
//
// THEN UNCOMMENT THE CODE BELOW
// fmt.Println(b)
}
// multi is a function that returns multiple int values
func multi() (int, int) {
return 5, 4
}
================================================
FILE: 06-variables/04-assignment/exercises/07-multi-short-func/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
_, b := multi()
fmt.Println(b)
}
func multi() (int, int) {
return 5, 4
}
================================================
FILE: 06-variables/04-assignment/exercises/08-swapper/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Swapper
//
// 1. Change `color` to "orange"
// and `color2` to "green" at the same time
//
// (use multiple-assignment)
//
// 2. Print the variables
//
// EXPECTED OUTPUT
// orange green
// ---------------------------------------------------------
func main() {
// UNCOMMENT THE CODE BELOW:
// color, color2 := "red", "blue"
// ?
}
================================================
FILE: 06-variables/04-assignment/exercises/08-swapper/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
color, color2 := "red", "blue"
color, color2 = "orange", "green"
fmt.Println(color, color2)
}
================================================
FILE: 06-variables/04-assignment/exercises/09-swapper-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Swapper #2
//
// 1. Swap the values of `red` and `blue` variables
//
// 2. Print them
//
// EXPECTED OUTPUT
// blue red
// ---------------------------------------------------------
func main() {
// UNCOMMENT THE CODE BELOW:
// red, blue := "red", "blue"
// ?
}
================================================
FILE: 06-variables/04-assignment/exercises/09-swapper-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
red, blue := "red", "blue"
red, blue = blue, red
fmt.Println(red, blue)
}
================================================
FILE: 06-variables/04-assignment/exercises/10-discard-the-file/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Discard The File
//
// 1. Print only the directory using `path.Split`
//
// 2. Discard the file part
//
// RESTRICTION
// Use short declaration
//
// EXPECTED OUTPUT
// secret/
// ---------------------------------------------------------
func main() {
// UNCOMMENT THE CODE BELOW:
// ? ?= path.Split("secret/file.txt")
}
================================================
FILE: 06-variables/04-assignment/exercises/10-discard-the-file/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"path"
)
func main() {
dir, _ := path.Split("secret/file.txt")
fmt.Println(dir)
}
================================================
FILE: 06-variables/04-assignment/exercises/README.md
================================================
# Assignments
Assignment means "copying" values. Everything is getting copied in Go. You'll learn more about this afterward.
Now, get your feet wet and try some assignment exercises.
1. **[Make It Blue](https://github.com/inancgumus/learngo/tree/master/06-variables/04-assignment/exercises/01-make-it-blue)**
2. **[Variables To Variables](https://github.com/inancgumus/learngo/tree/master/06-variables/04-assignment/exercises/02-vars-to-vars)**
3. **[Assign With Expressions](https://github.com/inancgumus/learngo/tree/master/06-variables/04-assignment/exercises/03-assign-with-expressions)**
4. **[Find the Rectangle's Perimeter](https://github.com/inancgumus/learngo/tree/master/06-variables/04-assignment/exercises/04-find-the-rectangle-perimeter)**
5. **[Multi Assign](https://github.com/inancgumus/learngo/tree/master/06-variables/04-assignment/exercises/05-multi-assign)**
6. **[Multi Assign #2](https://github.com/inancgumus/learngo/tree/master/06-variables/04-assignment/exercises/06-multi-assign-2)**
7. **[Multi Short Func](https://github.com/inancgumus/learngo/tree/master/06-variables/04-assignment/exercises/07-multi-short-func)**
8. **[Swapper](https://github.com/inancgumus/learngo/tree/master/06-variables/04-assignment/exercises/08-swapper)**
9. **[Swapper #2](https://github.com/inancgumus/learngo/tree/master/06-variables/04-assignment/exercises/09-swapper-2)**
10. **[Discard The File](https://github.com/inancgumus/learngo/tree/master/06-variables/04-assignment/exercises/10-discard-the-file)**
================================================
FILE: 06-variables/04-assignment/questions/README.md
================================================
## What happens when you assign a variable to another variable?
* The variables become the same variable
* Assignee variable gets deleted
* Variable's value is changed to the assigned variable's value *CORRECT*
## Which one is a correct assignment statement?
```go
opened := true
```
* `closed := true`
* `opened = false` *CORRECT*
* `var x = 2`
## Which one is a correct assignment statement?
* `a, b = 3; 5`
* `c, d = true, false` *CORRECT*
* `a, b, c = 5, 3`
## Which one is a correct assignment?
```go
var (
n = 3
m int
)
```
* `m = "4"`
* `n = 10` *CORRECT*
* `n = true`
* `m = false`
## Which one is a correct assignment?
```go
var (
n = 3
m int
f float64
)
// one of the assignments below will be here
fmt.Println(n, m, f)
```
* `n, m = 4, f`
* `n = false`
* `n, m, f = m + n, n + 5, 0.5` *CORRECT*
* `n, m = 3.82, "hi"`
## Which one is a correct assignment statement?
```go
var (
a int
c bool
)
```
* `a = _`
* `c, _ = _, false`
* `_, _ = a, c` *CORRECT*
## Which one is a correct assignment?
**REMEMBER:** `path.Split` returns two `string` values
```go
var c, f string
```
* `_ = path.Split("assets/profile.png")`
* `_, _, c = path.Split("assets/profile.png")`
* `f = path.Split("assets/profile.png")`
* `_, f = path.Split("assets/profile.png")` *CORRECT*
================================================
FILE: 06-variables/05-type-conversion/01-destructive/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
speed := 100 // int
force := 2.5 // float64
// ERROR: invalid op
// speed = speed * force
// conversion can be a destructive operation
// `force` loses its fractional part...
speed = speed * int(force)
fmt.Println(speed)
}
================================================
FILE: 06-variables/05-type-conversion/02-correct/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// order of conversion matters...
func main() {
speed := 100
force := 2.5
fmt.Printf("speed : %T\n", speed)
fmt.Printf("conversion: %T\n", float64(speed))
fmt.Printf("expression: %T\n", float64(speed)*force)
// TYPE MISMATCH:
// speed is int
// expression is float64
// speed = float64(speed) * force
// CORRECT: int * int
speed = int(float64(speed) * force)
fmt.Println(speed)
}
================================================
FILE: 06-variables/05-type-conversion/03-numeric-conversion/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var apple int
var orange int32
// ERROR:
// cannot assign orange to apple (different types)
// apple = orange
// you need to convert orange to apple
// orange is convertable to int because,
// int and int32 are both numeric types
apple = int(orange)
// you can't convert a numeric type to a bool:
// isDelicious := bool(orange)
// but you can convert an int to a string
// this only works with int types
orange = 65 // 65 is A
color := string(orange)
fmt.Println(color)
// this doesn't work. 65.0 is a float.
// fmt.Println(string(65.0))
// this works: there are two byte values
// byte is also an int
fmt.Println(string([]byte{104, 105}))
_ = apple
}
================================================
FILE: 06-variables/05-type-conversion/exercises/01-convert-and-fix/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Convert and Fix
//
// Fix the code by using the conversion expression.
//
// EXPECTED OUTPUT
// 15.5
// ---------------------------------------------------------
func main() {
// a, b := 10, 5.5
// fmt.Println(a + b)
}
================================================
FILE: 06-variables/05-type-conversion/exercises/01-convert-and-fix/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
a, b := 10, 5.5
fmt.Println(float64(a) + b)
}
================================================
FILE: 06-variables/05-type-conversion/exercises/02-convert-and-fix-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Convert and Fix #2
//
// Fix the code by using the conversion expression.
//
// EXPECTED OUTPUT
// 10.5
// ---------------------------------------------------------
func main() {
// a, b := 10, 5.5
// a = b
// fmt.Println(a + b)
}
================================================
FILE: 06-variables/05-type-conversion/exercises/02-convert-and-fix-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
a, b := 10, 5.5
a = int(b)
fmt.Println(float64(a) + b)
}
================================================
FILE: 06-variables/05-type-conversion/exercises/03-convert-and-fix-3/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Convert and Fix #3
//
// Fix the code.
//
// EXPECTED OUTPUT
// 5.5
// ---------------------------------------------------------
func main() {
// fmt.Println(int(5.5))
}
================================================
FILE: 06-variables/05-type-conversion/exercises/03-convert-and-fix-3/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println(5.5)
}
================================================
FILE: 06-variables/05-type-conversion/exercises/04-convert-and-fix-4/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Convert and Fix #4
//
// Fix the code.
//
// EXPECTED OUTPUT
// 9.5
// ---------------------------------------------------------
func main() {
// age := 2
// fmt.Println(int(7.5) + int(age))
}
================================================
FILE: 06-variables/05-type-conversion/exercises/04-convert-and-fix-4/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
age := 2
fmt.Println(7.5 + float64(age))
}
================================================
FILE: 06-variables/05-type-conversion/exercises/05-convert-and-fix-5/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Convert and Fix #5
//
// Fix the code.
//
// HINTS
// maximum of int8 can be 127
// maximum of int16 can be 32767
//
// EXPECTED OUTPUT
// 1127
// ---------------------------------------------------------
func main() {
// DO NOT TOUCH THESE VARIABLES
min := int8(127)
max := int16(1000)
// FIX THE CODE HERE
fmt.Println(int8(max) + min)
}
================================================
FILE: 06-variables/05-type-conversion/exercises/05-convert-and-fix-5/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
min := int8(127)
max := int16(1000)
fmt.Println(max + int16(min))
// EXPLANATION
//
// `int8(max)` destroys the information of max
// It reduces it to 127
// Which is the maximum value of int8
//
// Correct conversion is int16(min)
// Because, int16 > int8
// When you do so, min doesn't lose information
//
// You will learn more about this in
// the "Go Type System" section.
}
================================================
FILE: 06-variables/05-type-conversion/exercises/README.md
================================================
# Type Conversion
Here are 5 exercises for you. You must find the errors and then fix them using the correct type conversions.
1. **[Convert and Fix #1](https://github.com/inancgumus/learngo/tree/master/06-variables/05-type-conversion/exercises/01-convert-and-fix)**
2. **[Convert and Fix #2](https://github.com/inancgumus/learngo/tree/master/06-variables/05-type-conversion/exercises/02-convert-and-fix-2)**
3. **[Convert and Fix #3](https://github.com/inancgumus/learngo/tree/master/06-variables/05-type-conversion/exercises/03-convert-and-fix-3)**
4. **[Convert and Fix #4](https://github.com/inancgumus/learngo/tree/master/06-variables/05-type-conversion/exercises/04-convert-and-fix-4)**
5. **[Convert and Fix #5](https://github.com/inancgumus/learngo/tree/master/06-variables/05-type-conversion/exercises/05-convert-and-fix-5)**
================================================
FILE: 06-variables/05-type-conversion/questions/questions.md
================================================
## Which one is a correct type conversion expression?
* convert(40)
* var("hi")
* int(4.) *CORRECT*
* int[4]
## What does this code print?
```go
age := 6.5
fmt.Print(int(age))
```
* 6.5
* 65
* 6 *CORRECT*
* .5
> When you convert a float to integer
> It loses its fractional part
## What does this code print?
```go
fmt.Print(int(6.5))
```
* 6.5
* 65
* 6
* Compile-Time Error *CORRECT*
> Go can detect conversion errors at the compile-time
## What does this code print?
```go
area := 10.5
fmt.Print(area/2)
```
* 5.25 *CORRECT*
* 5
* 0
* Error
## What does this code print?
```go
area := 10.5
div := 2
fmt.Print(area/div)
```
* 5.25
* 5
* ERROR *CORRECT*
> You can't divide different type of values.
> You need to convert: `area / float64(div)`
## Which code below can fix the following code?
```go
area := 10.5
div := 2
fmt.Print(area/div)
```
* `fmt.Print(int(area)/div)` // 5
* `fmt.Print(area/int(div))` // type mismatch
* `fmt.Print(int(area)/int(div))` // 5
* `fmt.Print(area/float64(div))` *CORRECT*
================================================
FILE: 06-variables/06-project-greeter/01-demonstration/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// NOTE: RUN THIS WITH 3 ARGUMENTS AT LEAST
// OR, THERE WILL BE AN ERROR
func main() {
fmt.Printf("%#v\n", os.Args)
// Gets an item from the os.Args string slice:
// os.Args[INDEX]
// INDEX can be 0 or greater
fmt.Println("Path:", os.Args[0])
fmt.Println("1st argument:", os.Args[1])
fmt.Println("2nd argument:", os.Args[2])
fmt.Println("3rd argument:", os.Args[3])
// `len` function can find how many items
// inside a slice value
fmt.Println("Items inside os.Args:", len(os.Args))
}
================================================
FILE: 06-variables/06-project-greeter/02-version1/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// Since, you didn't learn about the control flow statements yet
// I didn't include an error detection here.
//
// So, if you don't pass a name,
// this program will fail.
// This is intentional.
func main() {
var name string
// assign a new value to the string variable below
name = os.Args[1]
fmt.Println("Hello great", name, "!")
// changes the name, declares the age with 85
name, age := "gandalf", 85
fmt.Println("My name is", name)
fmt.Println("My age is", age)
fmt.Println("BTW, you shall pass!")
}
================================================
FILE: 06-variables/06-project-greeter/03-version2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// Since, you didn't learn about the control flow statements yet
// I didn't include an error detection here.
//
// So, if you don't pass a name,
// this program will fail.
// This is intentional.
func main() {
// assign a new value to the string variable below
name := os.Args[1]
fmt.Println("Hello great", name, "!")
// changes the name, declares the age with 85
name, age := "gandalf", 85
fmt.Println("My name is", name)
fmt.Println("My age is", age)
fmt.Println("BTW, you shall pass!")
}
================================================
FILE: 06-variables/06-project-greeter/exercises/01-count-arguments/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Count the Arguments
//
// Print the count of the command-line arguments
//
// INPUT
// bilbo balbo bungo
//
// EXPECTED OUTPUT
// There are 3 names.
// ---------------------------------------------------------
func main() {
// UNCOMMENT & FIX THIS CODE
// count := ?
// UNCOMMENT IT & THEN DO NOT TOUCH THIS CODE
// fmt.Printf("There are %d names.\n", count)
}
================================================
FILE: 06-variables/06-project-greeter/exercises/01-count-arguments/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
count := len(os.Args) - 1
fmt.Printf("There are %d names.\n", count)
}
================================================
FILE: 06-variables/06-project-greeter/exercises/02-print-the-path/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print the Path
//
// Print the path of the running program by getting it
// from `os.Args` variable.
//
// HINT
// Use `go build` to build your program.
// Then run it using the compiled executable program file.
//
// EXPECTED OUTPUT SHOULD INCLUDE THIS
// myprogram
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 06-variables/06-project-greeter/exercises/02-print-the-path/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// STEPS:
//
// Compile it by typing:
// go build -o myprogram
//
// Then run it by typing:
// ./myprogram
//
// If you're on Windows, then type:
// myprogram
func main() {
fmt.Println(os.Args[0])
}
================================================
FILE: 06-variables/06-project-greeter/exercises/03-print-your-name/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print Your Name
//
// Get it from the first command-line argument
//
// INPUT
// Call the program using your name
//
// EXPECTED OUTPUT
// It should print your name
//
// EXAMPLE
// go run main.go inanc
//
// inanc
//
// BONUS: Make the output like this:
//
// go run main.go inanc
// Hi inanc
// How are you?
// ---------------------------------------------------------
func main() {
// get your name from the command-line
// and print it
}
================================================
FILE: 06-variables/06-project-greeter/exercises/03-print-your-name/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println(os.Args[1])
// BONUS SOLUTION:
fmt.Println("Hello", os.Args[1])
fmt.Println("How are you?")
}
================================================
FILE: 06-variables/06-project-greeter/exercises/04-greet-more-people/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Greet More People
//
// RESTRICTIONS
// 1. Be sure to match the expected output below
// 2. Store the length of the arguments in a variable
// 3. Store all the arguments in variables as well
//
// INPUT
// bilbo balbo bungo
//
// EXPECTED OUTPUT
// There are 3 people!
// Hello great bilbo !
// Hello great balbo !
// Hello great bungo !
// Nice to meet you all.
// ---------------------------------------------------------
func main() {
// TYPE YOUR CODE HERE
// BONUS #1:
// Observe the error if you pass less then 3 arguments.
// Search on the web how to solve that.
}
================================================
FILE: 06-variables/06-project-greeter/exercises/04-greet-more-people/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
var (
l = len(os.Args) - 1
n1 = os.Args[1]
n2 = os.Args[2]
n3 = os.Args[3]
)
fmt.Println("There are", l, "people !")
fmt.Println("Hello great", n1, "!")
fmt.Println("Hello great", n2, "!")
fmt.Println("Hello great", n3, "!")
fmt.Println("Nice to meet you all.")
}
================================================
FILE: 06-variables/06-project-greeter/exercises/05-greet-5-people/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Greet 5 People
//
// Greet 5 people this time.
//
// Please do not copy paste from the previous exercise!
//
// RESTRICTION
// This time do not use variables.
//
// INPUT
// bilbo balbo bungo gandalf legolas
//
// EXPECTED OUTPUT
// There are 5 people!
// Hello great bilbo !
// Hello great balbo !
// Hello great bungo !
// Hello great gandalf !
// Hello great legolas !
// Nice to meet you all.
// ---------------------------------------------------------
func main() {
// TYPE YOUR CODE HERE
}
================================================
FILE: 06-variables/06-project-greeter/exercises/05-greet-5-people/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("There are", len(os.Args)-1, "people !")
fmt.Println("Hello great", os.Args[1], "!")
fmt.Println("Hello great", os.Args[2], "!")
fmt.Println("Hello great", os.Args[3], "!")
fmt.Println("Hello great", os.Args[4], "!")
fmt.Println("Hello great", os.Args[5], "!")
fmt.Println("Nice to meet you all.")
}
================================================
FILE: 06-variables/06-project-greeter/exercises/README.md
================================================
# Command Line Arguments
1. **[Count the Arguments](https://github.com/inancgumus/learngo/tree/master/06-variables/06-project-greeter/exercises/01-count-arguments)**
2. **[Print the Path](https://github.com/inancgumus/learngo/tree/master/06-variables/06-project-greeter/exercises/02-print-the-path)**
3. **[Print Your Name](https://github.com/inancgumus/learngo/tree/master/06-variables/06-project-greeter/exercises/03-print-your-name)**
4. **[Greet More People](https://github.com/inancgumus/learngo/tree/master/06-variables/06-project-greeter/exercises/04-greet-more-people)**
5. **[Greet 5 People](https://github.com/inancgumus/learngo/tree/master/06-variables/06-project-greeter/exercises/05-greet-5-people)**
================================================
FILE: 06-variables/06-project-greeter/exercises/solution-to-the-lecture-exercise/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// ---------------------------------------------------------
// This is a solution to the exercise that I asked
// in the lecture.
// ---------------------------------------------------------
// NOTE: You should run this program with 3 arguments
// at least. Or there will be an error.
func main() {
// assign a new value to the string variable below
var (
name = os.Args[1]
name2 = os.Args[2]
name3 = os.Args[3]
)
fmt.Println("Hello great", name, "!")
fmt.Println("And hellooo to you magnificient", name2, "!")
fmt.Println("Welcome", name3, "!")
// changes the name, declares the age with 131
name, age := "bilbo baggins", 131 // unknown age!
fmt.Println("My name is", name)
fmt.Println("My age is", age)
fmt.Println("And, I love adventures!")
}
================================================
FILE: 06-variables/06-project-greeter/questions/questions.md
================================================
## What's does `os.Args` variable store in its first item?
* The first argument that is passed to the program
* The second argument that is passed to the program
* Path to the running program *CORRECT*
## What's the type of the `Args` variable?
```go
var Args []string
```
* string
* string array
* a slice of strings *CORRECT*
## What is the type of each value in the `Args` variable?
```go
var Args []string
```
* string *CORRECT*
* string array
* a slice of strings
## How to get the first item of the `Args` variable?
```go
var Args []string
```
* Args.0
* Args{1}
* Args[0] *CORRECT*
* Args(1)
## How to get the second item of the `Args` variable?
```go
var Args []string
```
* Args.2
* Args[1] *CORRECT*
* Args{1}
* Args(2)
## How to get the length of the `Args` variable?
```go
var Args []string
```
* length(Args)
* Args.len
* len(Args) *CORRECT*
* Args.Length
## How to get the first "argument" from the command-line?
* os.Args[0]
* os.Args[1] *CORRECT*
* os.Args[2]
* os.Args[3]
================================================
FILE: 07-printf/01-intro/01-println-vs-printf/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
ops, ok, fail := 2350, 543, 433
fmt.Println(
"total:", ops, "- success:", ok, "/", fail,
)
fmt.Printf(
"total: %d - success: %d / %d\n",
ops, ok, fail,
)
}
================================================
FILE: 07-printf/01-intro/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var brand string
// prints the string in quoted-form like this ""
fmt.Printf("%q\n", brand)
brand = "Google"
fmt.Printf("%q\n", brand)
}
================================================
FILE: 07-printf/02-escape-sequences/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// without newline
fmt.Println("hihi")
// with newline:
// \n = escape sequence
// \ = escape character
fmt.Println("hi\nhi")
// escape characters:
// \\ = \
// \" = "
fmt.Println("hi\\n\"hi\"")
}
================================================
FILE: 07-printf/03-printing-types/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// I'm using multiple declarations instead of singular
var (
speed int
heat float64
off bool
brand string
)
fmt.Printf("%T\n", speed)
fmt.Printf("%T\n", heat)
fmt.Printf("%T\n", off)
fmt.Printf("%T\n", brand)
}
================================================
FILE: 07-printf/04-coding/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
planet = "venus"
distance = 261
orbital = 224.701
hasLife = false
)
// swiss army knife %v verb
fmt.Printf("Planet: %v\n", planet)
fmt.Printf("Distance: %v millions kms\n", distance)
fmt.Printf("Orbital Period: %v days\n", orbital)
fmt.Printf("Does %v have life? %v\n", planet, hasLife)
// argument indexing - indexes start from 1
fmt.Printf(
"%v is %v away. Think! %[2]v kms! %[1]v OMG.\n",
planet, distance,
)
// why use other verbs than? because: type-safety
// uncomment to see the warnings:
//
// fmt.Printf("Planet: %d\n", planet)
// fmt.Printf("Distance: %s millions kms\n", distance)
// fmt.Printf("Orbital Period: %t days\n", orbital)
// fmt.Printf("Does %v has life? %f\n", planet, hasLife)
// correct verbs:
// fmt.Printf("Planet: %s\n", planet)
// fmt.Printf("Distance: %d millions kms\n", distance)
// fmt.Printf("Orbital Period: %f days\n", orbital)
// fmt.Printf("Does %s has life? %t\n", planet, hasLife)
// precision
fmt.Printf("Orbital Period: %f days\n", orbital)
fmt.Printf("Orbital Period: %.0f days\n", orbital)
fmt.Printf("Orbital Period: %.1f days\n", orbital)
fmt.Printf("Orbital Period: %.2f days\n", orbital)
}
================================================
FILE: 07-printf/exercises/01-print-your-age/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print Your Age
//
// Print your age using Printf
//
// EXPECTED OUTPUT
// I'm 30 years old.
//
// NOTE
// You should change 30 to your age, of course.
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: 07-printf/exercises/01-print-your-age/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("I'm %d years old.\n", 30)
}
================================================
FILE: 07-printf/exercises/02-print-your-name-and-lastname/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print Your Name and LastName
//
// Print your name and lastname using Printf
//
// EXPECTED OUTPUT
// My name is Inanc and my lastname is Gumus.
//
// BONUS
// Store the formatting specifier (first argument of Printf)
// in a variable.
// Then pass it to printf
// ---------------------------------------------------------
func main() {
// BONUS: Use a variable for the format specifier
// fmt.Printf("?", ?, ?)
}
================================================
FILE: 07-printf/exercises/02-print-your-name-and-lastname/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("My name is %s and my lastname is %s.\n", "Inanc", "Gumus")
// BONUS
msg := "My name is %s and my lastname is %s.\n"
fmt.Printf(msg, "Inanc", "Gumus")
}
================================================
FILE: 07-printf/exercises/03-false-claims/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: False Claims
//
// Use printf to print the expected output using a variable.
//
// EXPECTED OUTPUT
// These are false claims.
// ---------------------------------------------------------
func main() {
// UNCOMMENT THE FOLLOWING CODE
// AND DO NOT CHANGE IT AFTERWARDS
// tf := false
// TYPE YOUR CODE HERE
// ?
}
================================================
FILE: 07-printf/exercises/03-false-claims/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
tf := false
fmt.Printf("These are %t claims.\n", tf)
}
================================================
FILE: 07-printf/exercises/04-print-the-temperature/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print the Temperature
//
// Print the current temperature in your area using Printf
//
// NOTE
// Do not use %v verb
// Output "shouldn't" be like 29.500000
//
// EXPECTED OUTPUT
// Temperature is 29.5 degrees.
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: 07-printf/exercises/04-print-the-temperature/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("Temperature is %.1f degrees.\n", 29.5)
}
================================================
FILE: 07-printf/exercises/05-double-quotes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Double Quotes
//
// Print "hello world" with double-quotes using Printf
// (As you see here)
//
// NOTE
// Output "shouldn't" be just: hello world
//
// EXPECTED OUTPUT
// "hello world"
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: 07-printf/exercises/05-double-quotes/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("%q\n", "hello world")
}
================================================
FILE: 07-printf/exercises/06-print-the-type/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print the Type
//
// Print the type and value of 3 using fmt.Printf
//
// EXPECTED OUTPUT
// Type of 3 is int
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: 07-printf/exercises/06-print-the-type/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("Type of %d is %[1]T\n", 3)
}
================================================
FILE: 07-printf/exercises/07-print-the-type-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print the Type #2
//
// Print the type and value of 3.14 using fmt.Printf
//
// EXPECTED OUTPUT
// Type of 3.14 is float64
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: 07-printf/exercises/07-print-the-type-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("Type of %.2f is %[1]T\n", 3.14)
}
================================================
FILE: 07-printf/exercises/08-print-the-type-3/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print the Type #3
//
// Print the type and value of "hello" using fmt.Printf
//
// EXPECTED OUTPUT
// Type of hello is string
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: 07-printf/exercises/08-print-the-type-3/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("Type of %s is %[1]T\n", "hello")
}
================================================
FILE: 07-printf/exercises/09-print-the-type-4/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print the Type #4
// Print the type and value of true using fmt.Printf
//
// EXPECTED OUTPUT
// Type of true is bool
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: 07-printf/exercises/09-print-the-type-4/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("Type of %t is %[1]T\n", true)
}
================================================
FILE: 07-printf/exercises/10-print-your-fullname/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print Your Fullname
//
// 1. Get your name and lastname from the command-line
// 2. Print them using Printf
//
// EXAMPLE INPUT
// Inanc Gumus
//
// EXPECTED OUTPUT
// Your name is Inanc and your lastname is Gumus.
// ---------------------------------------------------------
func main() {
// BONUS: Use a variable for the format specifier
}
================================================
FILE: 07-printf/exercises/10-print-your-fullname/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
// WARNING: This program will error
// if you don't pass your name and lastname
name, lastname := os.Args[1], os.Args[2]
msg := "Your name is %s and your lastname is %s.\n"
fmt.Printf(msg, name, lastname)
}
================================================
FILE: 07-printf/exercises/README.md
================================================
# Printf
1. **[Print Your Age](https://github.com/inancgumus/learngo/tree/07-printf/exercises/01-print-your-age)**
2. **[Print Your Name and LastName](https://github.com/inancgumus/learngo/tree/07-printf/exercises/02-print-your-name-and-lastname)**
3. **[False Claims](https://github.com/inancgumus/learngo/tree/07-printf/exercises/03-false-claims)**
4. **[Print the Temperature](https://github.com/inancgumus/learngo/tree/07-printf/exercises/04-print-the-temperature)**
5. **[Double Quotes](https://github.com/inancgumus/learngo/tree/07-printf/exercises/05-double-quotes)**
6. **[Print the Type](https://github.com/inancgumus/learngo/tree/07-printf/exercises/06-print-the-type)**
7. **[Print the Type #2](https://github.com/inancgumus/learngo/tree/07-printf/exercises/07-print-the-type-2)**
8. **[Print the Type #3](https://github.com/inancgumus/learngo/tree/07-printf/exercises/08-print-the-type-3)**
9. **[Print the Type #4](https://github.com/inancgumus/learngo/tree/07-printf/exercises/09-print-the-type-4)**
10. **[Print Your Fullname](https://github.com/inancgumus/learngo/tree/07-printf/exercises/10-print-your-fullname)**
================================================
FILE: 07-printf/questions/questions.md
================================================
## Which code is correct?
* `fmt.Printf("Hi %s")`
* `fmt.Printf("Hi %s", "how", "are you")`
* `fmt.Printf("Hi %s", "hello")` *CORRECT*
* `fmt.Printf("Hi %s", true)`
## Which code is correct?
* `fmt.Printf("Hi %s %s", "there")`
* `fmt.Printf("Hi %s %s", "5", true)`
* `fmt.Printf("Hi %s %s", "there", ".")` *CORRECT*
* `fmt.Printf("Hi %s %s", "true", false)`
## Which verb is used for an int value?
* %f
* %d *CORRECT*
* %s
* %t
## Which verb is used for a float value?
* %f *CORRECT*
* %d
* %s
* %t
## Which verb is used for a string value?
* %f
* %d
* %s *CORRECT*
* %t
## Which verb is used for a bool value?
* %f
* %d
* %s
* %t *CORRECT*
## Which verb you can use for any type of value?
* %f
* %d
* %v *CORRECT*
* %t
## What does `"\n"` print?
* \n
* Prints a newline *CORRECT*
* Prints an empty string
## What does `"\\n"` print?
* \n *CORRECT*
* Prints a newline
* Prints an empty string
## What does "c:\\secret\\directory" print?
* "c:\\secret\\directory"
* c:\\secret\\directory
* c:\secret\directory *CORRECT*
## What does `"\"heisenberg\""` print?
* ERROR
* heisenberg
* "heisenberg" *CORRECT*
* 'heisenberg'
## What does `fmt.Printf("%T", 3.14)` print?
* ERROR
* int
* float64 *CORRECT*
* string
* bool
## What does `fmt.Printf("%T", true)` print?
* ERROR
* int
* float64
* string
* bool *CORRECT*
## What does `fmt.Printf("%T", 42)` print?
* ERROR
* int *CORRECT*
* float64
* string
* bool
## What does `fmt.Printf("%T", "hi")` print?
* ERROR
* int
* float64
* string *CORRECT*
* bool
================================================
FILE: 08-numbers-and-strings/01-numbers/01-arithmetic-operators/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// when an integer and a float value used together
// in an expression, the result always becomes
// a float value
fmt.Println(8 * -4.0) // -32.0 not -32
// two integer values result in an integer value
fmt.Println(-4 / 2)
// remainder operator
// it can only used with integers
fmt.Println(5 % 2)
// fmt.Println(5.0 % 2) // wrong
// addition operators
fmt.Println(1 + 2.5)
fmt.Println(2 - 3)
// negation operator
fmt.Println(-(-2))
fmt.Println(- -2) // this also works
}
================================================
FILE: 08-numbers-and-strings/01-numbers/01-arithmetic-operators/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
myAge = 30
yourAge = 35
average float64
)
average = float64(myAge+yourAge) / 2
fmt.Println(average)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/01-arithmetic-operators/03-float-inaccuracy/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
ratio := 1.0 / 10.0
// after 10 operations
// the inaccuracy is clear
//
// BTW, don't mind about this loop syntax for now
// I'm going to explain it afterwards
for range [...]int{10: 0} {
ratio += 1.0 / 10.0
}
fmt.Printf("%.60f", ratio)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/01-arithmetic-operators/03-float-inaccuracy/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// Go compiler sees these numbers as integers,
// since, there are no fractional parts in
// integer values,
// So, the result becomes 1 instead of 1.5
// So, ratio variable here is an int variable,
// it's because, 3 divided by 2 results
// in an integer.
ratio := 3 / 2
fmt.Printf("%d", ratio)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/01-arithmetic-operators/03-float-inaccuracy/03/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// When you use a float value with an integer
// in a calculation,
// the result always becomes a float.
ratio := 3.0 / 2
// OR:
// ratio = 3 / 2.0
// OR - if 3 is inside an int variable:
// n := 3
// ratio = float64(n) / 2
fmt.Printf("%f", ratio)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/02-arithmetic-operators-examples/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("sum :", 3+2) // sum - int
fmt.Println("sum :", 2+3.5) // sum - float64
fmt.Println("dif :", 3-1) // difference - int
fmt.Println("dif :", 3-0.5) // difference - float64
fmt.Println("prod:", 4*5) // product - int
fmt.Println("prod:", 5*2.5) // product - float64
fmt.Println("quot:", 8/2) // quotient - int
fmt.Println("quot:", 8/1.5) // quotient - float64
// remainder is only for integers
fmt.Println("rem :", 8%3)
// fmt.Println("rem:", 8.0%3) // error
// you can do this
// since the fractional part of a float is zero
f := 8.0
fmt.Println("rem :", int(f)%3)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/02-arithmetic-operators-examples/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// what's the value of the ratio?
// 3 / 2 = 1.5?
var ratio float64 = 3 / 2
fmt.Println(ratio)
// explain
// above expression equals to this:
ratio = float64(int(3) / int(2))
fmt.Println(ratio)
// how to fix it?
//
// remember, when one of the values is a float value
// the result becomes a float
ratio = float64(3) / 2
fmt.Println(ratio)
// or
ratio = 3.0 / 2
fmt.Println(ratio)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/03-precedence/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println(
2+2*4/2,
2+((2*4)/2), // same as above
)
fmt.Println(
1+4-2,
(1+4)-2, // same as above
)
fmt.Println(
(2+2)*4/2,
(2+2)*(4/2), // same as above
)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/03-precedence/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
n, m := 1, 5
fmt.Println(2 + 1*m/n)
fmt.Println(2 + ((1 * m) / n)) // same as above
// let's change the precedence using parentheses
fmt.Println(((2 + 1) * m) / n)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/03-precedence/03/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// // Precedence: Order of expressions
// // Multiplication operators runs first: * and /
// fmt.Println(
// 1 + 5 - 3*10/2,
// )
// // 3 * 10 = 30
// // 30 / 2 = 15
// // 1 + 5 = 6
// // 6 - 15 = -9
// // **** TIP ****
// // Use parentheses to change the order of evaluation.
// // First, (1+5-3), then (10/2) will be calculated.
// fmt.Println(
// (1 + 5 - 3) * (10 / 2),
// )
}
================================================
FILE: 08-numbers-and-strings/01-numbers/03-precedence/04/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
celsius := 35.
// Wrong formula : 9*celsius + 160 / 5
// Correct formula: (9*celsius + 160) / 5
fahrenheit := (9*celsius + 160) / 5
fmt.Printf("%g ºC is %g ºF\n", celsius, fahrenheit)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/04-incdec-statement/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var n int
// ALTERNATIVES:
// n = n + 1
// n += 1
// BETTER:
n++
fmt.Println(n)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/04-incdec-statement/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
n := 10
// ALTERNATIVES:
// n = n - 1
// n -= 1
// BETTER:
n--
fmt.Println(n)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/04-incdec-statement/03/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// incdec is a statement
func main() {
var counter int
// following "statements" are correct:
counter++ // 1
counter++ // 2
counter++ // 3
counter-- // 2
fmt.Printf("There are %d line(s) in the file\n",
counter)
// the following "expressions" are incorrect:
// counter = 5+counter--
// counter = ++counter + counter--
}
================================================
FILE: 08-numbers-and-strings/01-numbers/05-assignment-operations/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
width, height := 5., 12.
// calculates the area of a rectangle
area := width * height
fmt.Printf("%gx%g=%g\n", width, height, area)
area = area - 10 // decreases area by 10
area = area + 10 // increases area by 10
area = area * 2 // doubles the area
area = area / 2 // divides the area by 2
fmt.Printf("area=%g\n", area)
// // ASSIGNMENT OPERATIONS
area -= 10 // decreases area by 10
area += 10 // increases area by 10
area *= 2 // doubles the area
area /= 2 // divides the area by 2
fmt.Printf("area=%g\n", area)
// finds the remainder of area variable
// since: area is float, this won't work:
// area %= 7
// this works
area = float64(int(area) % 7)
fmt.Printf("area=%g\n", area)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/06-project-feet-to-meters/exercise-solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
c, _ := strconv.ParseFloat(os.Args[1], 64)
f := c*1.8 + 32
// Like this:
fmt.Printf("%g ºC is %g ºF\n", c, f)
// Or just like this (both are correct):
fmt.Printf("%g ºF\n", f)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/06-project-feet-to-meters/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
arg := os.Args[1]
// feet is a float64 now
feet, _ := strconv.ParseFloat(arg, 64)
meters := feet * 0.3048
fmt.Printf("%f feet is %f meters.\n", feet, meters)
// pretty print it:
// fmt.Printf("%g feet is %g meters.\n", feet, meters)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/01-do-some-calculations/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Do Some Calculations
//
// 1. Print the sum of 50 and 25
// 2. Print the difference of 50 and 15.5
// 3. Print the product of 50 and 0.5
// 4. Print the quotient of 50 and 0.5
// 5. Print the remainder of 25 and 3
// 6. Print the negation of `5 + 2`
//
// EXPECTED OUTPUT
// 75
// 34.5
// 25
// 100
// 1
// -7
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/01-do-some-calculations/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println(50 + 25)
fmt.Println(50 - 15.5)
fmt.Println(50 * 0.5)
fmt.Println(50 / 0.5)
fmt.Println(25 % 3)
fmt.Println(-(5 + 2))
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/02-fix-the-float/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Fix the Float
//
// Fix the program to print 2.5 instead of 2
//
// EXPECTED OUTPUT
// 2.5
// ---------------------------------------------------------
func main() {
x := 5 / 2
fmt.Println(x)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/02-fix-the-float/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// Below solutions are correct:
x := 5. / 2
// x := 5 / 2.
// x := float64(5) / 2
// x := 5 / float64(2)
fmt.Println(x)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/03-precedence/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Precedence
//
// Change the expressions to produce the expected outputs
//
// RESTRICTION
// Use parentheses to change the precedence
// ---------------------------------------------------------
func main() {
// This expression should print 20
fmt.Println(10 + 5 - 5 - 10)
// This expression should print -16
fmt.Println(-10 + 0.5 - 1 + 5.5)
// This expression should print -25
fmt.Println(5 + 10*2 - 5)
// This expression should print 0.5
fmt.Println(0.5*2 - 1)
// This expression should print 24
fmt.Println(3 + 1/2*10 + 4)
// This expression should print 15
fmt.Println(10 / 2 * 10 % 7)
// This expression should print 40
// Note that you may need to use floats to solve this
fmt.Println(100 / 5 / 2)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/03-precedence/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// 10 + 5 - 5 - 10
fmt.Println(10 + 5 - (5 - 10))
// -10 + 0.5 - 1 + 5.5
fmt.Println(-10 + 0.5 - (1 + 5.5))
// 5 + 10*2 - 5
fmt.Println(5 + 10*(2-5))
// 0.5*2 - 1
fmt.Println(0.5 * (2 - 1))
// 3 + 1/2*10 + 4
fmt.Println((3+1)/2*10 + 4)
// 10 / 2 * 10 % 7
fmt.Println(10 / 2 * (10 % 7))
// 100 / 5 / 2
// 5 / 2 = 2
// 5 and 2 are integers, so, the fractional part drops
// 5. / 2 = 2.5
// because 5. is a float, so the result becomes a float
fmt.Println(100 / (5. / 2))
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/04-incdecs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Incdecs
//
// 1. Increase the `counter` 5 times
// 2. Decrease the `factor` 2 times
// 3. Print the product of counter and factor
//
// RESTRICTION
// Use only the incdec statements
//
// EXPECTED OUTPUT
// -75
// ---------------------------------------------------------
func main() {
// DO NOT TOUCH THIS
counter, factor := 45, 0.5
// TYPE YOUR CODE BELOW
// ...
// LASTLY: REMOVE THE CODE BELOW
_, _ = counter, factor
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/04-incdecs/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
counter, factor := 45, 0.5
counter++
counter++
counter++
counter++
counter++
factor--
factor--
fmt.Println(float64(counter) * factor)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/05-manipulate-a-counter/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Manipulate a Counter
//
// 1. Write the simplest line of code to increase
// the counter variable by 1.
//
// 2. Write the simplest line of code to decrease
// the counter variable by 1.
//
// 3. Write the simplest line of code to increase
// the counter variable by 5.
//
// 4. Write the simplest line of code to multiply
// the counter variable by 10.
//
// 5. Write the simplest line of code to divide
// the counter variable by 5.
//
// EXPECTED OUTPUT
// 10
// ---------------------------------------------------------
func main() {
// DO NOT CHANGE THE CODE BELOW
var counter int
// TYPE YOUR CODE HERE
// DO NOT CHANGE THE CODE BELOW
fmt.Println(counter)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/05-manipulate-a-counter/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var counter int
counter++
counter--
counter += 5
counter *= 10
counter /= 5
fmt.Println(counter)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/06-simplify-the-assignments/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Simplify the Assignments
//
// Simplify the code (refactor)
//
// RESTRICTION
// Use only the incdec and assignment operations
//
// EXPECTED OUTPUT
// 3
// ---------------------------------------------------------
func main() {
width, height := 10, 2
width = width + 1
width = width + height
width = width - 1
width = width - height
width = width * 20
width = width / 25
width = width % 5
fmt.Println(width)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/06-simplify-the-assignments/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
width, height := 10, 2
width++
width += height
width--
width -= height
width *= 20
width /= 25
width %= 5
fmt.Println(width)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/07-circle-area/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// ---------------------------------------------------------
// EXERCISE: Circle Area
//
// Calculate the area of a circle from the given radius
//
// CIRCLE AREA FORMULA
// area = πr²
// https://en.wikipedia.org/wiki/Area#Circles
//
// HINT
// For PI you can use `math.Pi`
//
// EXPECTED OUTPUT
// radius: 10 -> area: 314.1592653589793
//
// BONUS EXERCISE!
// 1. Print the area as 314.16
// 2. To do that you need to use the correct Printf verb :)
// Instead of `%g` verb below.
//
// EXPECTED OUTPUT
// radius: 10 -> area: 314.16
// ---------------------------------------------------------
func main() {
var (
radius = 10.
area float64
)
// ADD YOUR CODE HERE
// ...
// DO NOT TOUCH THIS
fmt.Printf("radius: %g -> area: %g\n", radius, area)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/07-circle-area/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
)
func main() {
var (
radius = 10.
area float64
)
area = math.Pi * radius * radius
fmt.Printf("radius: %g -> area: %.2f\n",
radius, area)
// ALTERNATIVE:
// math.Pow calculates the power of a float number
// area = math.Pi * math.Pow(radius, 2)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/08-sphere-area/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// ---------------------------------------------------------
// EXERCISE: Sphere Area
//
// 1. Get the radius from the command-line
// 2. Convert it to a float64
// 3. Calculate the surface area of a sphere
//
// SPHERE SURFACE AREA FORMULA
// area = 4πr²
// https://en.wikipedia.org/wiki/Sphere#Surface_area
//
// RESTRICTION
// Use `math.Pow` to calculate the area
// Read its documentation to see how it works.
// https://golang.org/pkg/math/#Pow
//
// EXPECTED OUTPUT
// go run main.go 10
// 1256.64
//
// go run main.go 54.2
// 36915.47
// ---------------------------------------------------------
func main() {
var radius, area float64
// ADD YOUR CODE HERE
// ...
// DO NOT TOUCH THIS
fmt.Printf("radius: %g -> area: %.2f\n", radius, area)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/08-sphere-area/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
"os"
"strconv"
)
func main() {
var radius, area float64
radius, _ = strconv.ParseFloat(os.Args[1], 64)
area = 4 * math.Pi * math.Pow(radius, 2)
fmt.Printf("radius: %g -> area: %.2f\n",
radius, area)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/09-sphere-volume/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// ---------------------------------------------------------
// EXERCISE: Sphere Volume
//
// 1. Get the radius from the command-line
// 2. Convert it to a float64
// 3. Calculate the volume of a sphere
//
// SPHERE VOLUME FORMULA
// https://en.wikipedia.org/wiki/Sphere#Enclosed_volume
//
// RESTRICTION
// Use `math.Pow` to calculate the volume
//
// EXPECTED OUTPUT
// go run main.go 10
// 4188.79
//
// go run main.go .5
// 0.52
// ---------------------------------------------------------
func main() {
var radius, vol float64
// ADD YOUR CODE HERE
// ...
// DO NOT TOUCH THIS
fmt.Printf("radius: %g -> volume: %.2f\n", radius, vol)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/09-sphere-volume/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
"os"
"strconv"
)
func main() {
var radius, vol float64
radius, _ = strconv.ParseFloat(os.Args[1], 64)
vol = (4 * math.Pi * math.Pow(radius, 3)) / 3
fmt.Printf("radius: %g -> volume: %.2f\n", radius, vol)
}
================================================
FILE: 08-numbers-and-strings/01-numbers/exercises/README.md
================================================
# Numbers, Precedence, and Assignment Operations
1. **[Do Some Calculations](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/01-numbers/exercises/01-do-some-calculations)**
2. **[Fix the Float](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/01-numbers/exercises/02-fix-the-float)**
3. **[Precedence](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/01-numbers/exercises/03-precedence)**
4. **[IncDecs](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/01-numbers/exercises/04-incdecs)**
5. **[Manipulate a Counter](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/01-numbers/exercises/05-manipulate-a-counter)**
6. **[Simplify the Assignments](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/01-numbers/exercises/06-simplify-the-assignments)**
7. **[Circle Area](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/01-numbers/exercises/07-circle-area)**
8. **[Sphere Area](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/01-numbers/exercises/08-sphere-area)**
9. **[Sphere Volume](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/01-numbers/exercises/09-sphere-volume)**
================================================
FILE: 08-numbers-and-strings/01-numbers/questions/01-arithmetic-operators.md
================================================
## Which group of operators below is arithmetic operators?
1. **, /, ^, !, ++, --
2. *, /, %, +, - *CORRECT*
3. &, |, +, -, /
## Which value below you can use with a remainder operator?
1. 3.54
2. true
3. 57 *CORRECT*
4. "Try Me!"
> **4:** Nice Try. But, that's not right. Sorry.
>
> **3:** That's right. The remainder operator only works on integer values.
>
## What's the result of this expression?
```go
8 % 3
```
1. 4
2. 2 *CORRECT*
3. 0
4. 1
## What's the result of this expression?
```go
-(3 * -2)
```
1. -6
2. -1
3. 0
4. 6 *CORRECT*
## What's the result of this expression?
```go
var degree float64 = 10 / 4
```
1. 2.5
2. 2.49
3. 2 *CORRECT*
4. 0
> **3:** That's right. An integer value cannot contain fractional parts.
>
## What's the result of this expression?
```go
var degree float64 = 3. / 2
```
1. 1.5 *CORRECT*
2. 1.49
3. 1
4. 0
> **1:** That's right. `3.` makes the whole expression a float value.
>
## What's the type of the `x` variable?
```go
x := 5 * 2.
```
1. int
2. float64 *CORRECT*
3. bool
4. string
> **1:** Look closely to 2 there.
>
> **2:** Why? Because, `2.` there makes the expressions a float value. Cool.
>
> **3:** Oh, come on! Life is not always true and false.
>
> **4:** I can't see any double-quotes or back-quotes, can you?
>
## What's the type of the `x` variable?
```go
x := 5 * -(2)
```
1. int *CORRECT*
2. float64
3. bool
4. string
> **1:** Why? Because, there only integer numbers.
>
> **2:** I can't see any fractional parts there, can you?
>
> **3:** Oh, come on! Life is not always true and false.
>
> **4:** I can't see any double-quotes or back-quotes, can you?
>
## Which kind of values can result in inaccurate calculations?
1. integers
2. floats *CORRECT*
3. bools
4. strings
================================================
FILE: 08-numbers-and-strings/01-numbers/questions/02-precedence.md
================================================
## What's the result of the expression?
```go
5 - 2 * 5 + 7
```
1. 2 *CORRECT*
2. 22
3. -19
4. 36
5. -12
## What's the result of the expression?
```go
5 - (2 * 5) + 7
```
1. 2 *CORRECT*
2. 22
3. -19
4. 36
5. -12
> **1:** The expression can also be: 5 + (2 * 5) + 7
## What's the result of the expression?
```go
5 - 2 * (5 + 7)
```
1. 2
2. 22
3. -19 *CORRECT*
4. 36
5. -12
## What's the result of the expression?
```go
5. -(2 * 5 + 7)
```
1. 2
2. 22
3. -19
4. -12
5. -12.0 *CORRECT*
> **4:** You're close but remember! The result of an expression with floats and integers is always a float.
>
>
================================================
FILE: 08-numbers-and-strings/01-numbers/questions/03-assignment-operations.md
================================================
## Which expression increases `n` by 1?
```go
var n float64
```
1. `n = +1`
2. `n = n++`
3. `n = n + 1` *CORRECT*
4. `++n`
> **1:** This just assigns 1 to n.
>
> **2:** IncDec statement can't be used as an operator.
>
> **4:** Go doesn't support prefix incdec notation.
>
## Which expression decreases `n` by 1?
```go
var n int
```
1. `n = -1`
2. `n = n--`
3. `n = n - 1` *CORRECT*
4. `--n`
> **1:** This just assigns -1 to n.
>
> **2:** IncDec statement can't be used as an operator.
>
> **4:** Go doesn't support prefix incdec notation.
>
## Which code below equals to `n = n + 1`?
1. `n++` *CORRECT*
2. `n = n++`
3. `++n`
4. `n = n ++ 1`
> **2:** IncDec statement can't be used as an operator.
>
> **3:** Go doesn't support prefix incdec notation.
>
> **4:** What's that? ++?
>
## Which code below equals to `n = n + 1`?
1. `n = n++`
2. `n += 1` *CORRECT*
3. `++n`
4. `n = n ++ 1`
> **1:** IncDec statement can't be used as an operator.
>
> **3:** Go doesn't support prefix incdec notation.
>
> **4:** What's that? ++?
>
## Which code below equals to `n -= 1`?
1. `n = n--`
2. `n += 1--`
3. `n--` *CORRECT*
4. `--n`
> **1:** IncDec statement can't be used as an operator.
>
> **2:** IncDec statement can't be used as an operator. And also, you can't use it with `1--`. The value should be addressable. You're going to learn what that means soon.
>
> **4:** Go doesn't support prefix incdec notation.
>
## Which code below divides the `length` by 10?
1. `length = length // 10`
2. `length /= 10` *CORRECT*
3. `length //= 10`
> **1:** What's that? `//`?
>
> **2:** That's right. This equals to: `length = length / 10`
>
> **3:** What's that? `//=`?
>
## Which code below equals to `x = x % 2`?
1. `x = x / 2`
2. `x =% 2`
3. `x %= 2` *CORRECT*
> **1:** This is a division. You need to use the remainder operator.
>
> **2:** Close... But, the `%` operator is on the wrong side of the assignment.
>
## Which function below converts a string value into a float value?
1. `fmtconv.ToFloat`
2. `conv.ParseFloat`
3. `strconv.ParseFloat` *CORRECT*
4. `strconv.ToFloat`
## Which code is correct?
If you don't remember it, this its function signature:
```go
func ParseFloat(s string, bitSize int) (float64, error)
```
1. `strconv.ParseFloat("10", 128)`
2. `strconv.ParseFloat("10", 64)` *CORRECT*
3. `strconv.ParseFloat("10", "64")`
4. `strconv.ParseFloat(10, 64)`
> **1:** There are no 128-bit floating point values in Go (Actually there are, but they only belong to the compile-time).
>
================================================
FILE: 08-numbers-and-strings/02-strings/01-raw-string-literal/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// The type of a string and a raw string literal
// is the same. They both are strings.
//
// So, they both can be used as a string value.
var s string
s = "how are you?"
s = `how are you?`
fmt.Println(s)
// string literal
s = "\n\t\"Hello\"\n"
fmt.Println(s)
// raw string literal
s = `
"Hello"
`
fmt.Println(s)
// windows path
fmt.Println("c:\\my\\dir\\file") // string literal
fmt.Println(`c:\my\dir\file`) // raw string literal
}
================================================
FILE: 08-numbers-and-strings/02-strings/02-concatenation/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
name, last := "carl", "sagan"
fmt.Println(name + " " + last)
}
================================================
FILE: 08-numbers-and-strings/02-strings/02-concatenation/02-assignment-operation/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
name, last := "carl", "sagan"
// assignment operation using string concat
name += " edward"
// equals to this:
// name = name + " edward"
fmt.Println(name + " " + last)
}
================================================
FILE: 08-numbers-and-strings/02-strings/02-concatenation/03-concat-non-strings/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
)
func main() {
fmt.Println(
"hello" + ", " + "how" + " " + "are" + " " + "today?",
)
// you can combine raw string and string literals
fmt.Println(
`hello` + `, ` + `how` + ` ` + `are` + ` ` + "today?",
)
// ------------------------------------------
// Converting non-string values into string
// ------------------------------------------
eq := "1 + 2 = "
sum := 1 + 2
// invalid op
// string concat op can only be used with strings
// fmt.Println(eq + sum)
// you need to convert it using strconv.Itoa
// Itoa = Integer to ASCII
fmt.Println(eq + strconv.Itoa(sum))
//
// invalid op
// eq = true + " " + false
eq = strconv.FormatBool(true) +
" " +
strconv.FormatBool(false)
fmt.Println(eq)
}
================================================
FILE: 08-numbers-and-strings/02-strings/03-string-length/01-len/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
name := "carl"
// strings are made up of bytes
// len function counts the bytes in a string value
fmt.Println(len(name))
}
================================================
FILE: 08-numbers-and-strings/02-strings/03-string-length/02-unicode-len/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
// strings are made up of bytes
// len function counts the bytes in a string value.
//
// This string literal contains unicode characters.
//
// And, unicode characters can be 1-4 bytes.
// So, "İnanç" is 7 bytes long, not 5.
//
// İ = 2 bytes
// n = 1 byte
// a = 1 byte
// n = 1 byte
// ç = 2 bytes
// TOTAL = 7 bytes
name := "İnanç"
fmt.Printf("%q is %d bytes\n", name, len(name))
// To get the actual characters (or runes) inside
// a utf-8 encoded string value, you should do this:
fmt.Printf("%q is %d characters\n",
name, utf8.RuneCountInString(name))
}
================================================
FILE: 08-numbers-and-strings/02-strings/04-project-banger/exercise-solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"os"
"strings"
)
// NOTE: You should always pass it at least one argument
func main() {
msg := os.Args[1]
// it's important to calculate things only once
// so, do not call the repeat function twice
// calling it once is enough
marks := strings.Repeat("!", len(msg))
s := marks + msg + marks
s = strings.ToUpper(s)
// you can also type this program more concisely
// like this:
//
// msg := strings.ToUpper(os.Args[1])
// marks := strings.Repeat("!", len(msg))
// fmt.Println(marks + msg + marks)
}
================================================
FILE: 08-numbers-and-strings/02-strings/04-project-banger/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
// NOTE: You should always pass it at least one argument
func main() {
msg := os.Args[1]
l := len(msg)
s := msg + strings.Repeat("!", l)
s = strings.ToUpper(s)
fmt.Println(s)
}
================================================
FILE: 08-numbers-and-strings/02-strings/README.md
================================================
# Basic Strings
1. **[Windows Path](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/02-strings/exercises/01-windows-path)**
2. **[Print JSON](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/02-strings/exercises/02-print-json)**
3. **[Raw Concat](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/02-strings/exercises/03-raw-concat)**
4. **[Count the Chars](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/02-strings/exercises/04-count-the-chars)**
5. **[Improved Banger](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/02-strings/exercises/05-improved-banger)**
6. **[ToLowercase](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/02-strings/exercises/06-tolowercase)**
7. **[Trim It](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/02-strings/exercises/07-trim-it)**
8. **[Right Trim It](https://github.com/inancgumus/learngo/tree/master/08-numbers-and-strings/02-strings/exercises/08-right-trim-it)**
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/01-windows-path/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Windows Path
//
// 1. Change the following program
// 2. It should use a raw string literal instead
//
// HINT
// Run this program first to see its output.
// Then you can easily understand what it does.
//
// EXPECTED OUTPUT
// Your solution should output the same as this program.
// Only that it should use a raw string literal instead.
// ---------------------------------------------------------
func main() {
// HINTS:
// \\ equals to backslash character
// \n equals to newline character
path := "c:\\program files\\duper super\\fun.txt\n" +
"c:\\program files\\really\\funny.png"
fmt.Println(path)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/01-windows-path/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// this one uses a raw string literal
// can you see how readable it is?
// compared to the previous one?
path := `c:\program files\duper super\fun.txt
c:\program files\really\funny.png`
fmt.Println(path)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/02-print-json/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Print JSON
//
// 1. Change the following program
// 2. It should use a raw string literal instead
//
// HINT
// Run this program first to see its output.
// Then you can easily understand what it does.
//
// EXPECTED OUTPUT
// Your solution should output the same as this program.
// Only that it should use a raw string literal instead.
// ---------------------------------------------------------
func main() {
// HINTS:
// \t equals to TAB character
// \n equals to newline character
// \" equals to double-quotes character
json := "\n" +
"{\n" +
"\t\"Items\": [{\n" +
"\t\t\"Item\": {\n" +
"\t\t\t\"name\": \"Teddy Bear\"\n" +
"\t\t}\n" +
"\t}]\n" +
"}\n"
fmt.Println(json)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/02-print-json/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// this one uses a raw string literal
// can you see how readable it is?
// compared to the previous one?
json := `
{
"Items": [{
"Item": {
"name": "Teddy Bear"
}
}]
}`
fmt.Println(json)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/03-raw-concat/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Raw Concat
//
// 1. Initialize the name variable
// by getting input from the command line
//
// 2. Use concatenation operator to concatenate it
// with the raw string literal below
//
// NOTE
// You should concatenate the name variable in the correct
// place.
//
// EXPECTED OUTPUT
// Let's say that you run the program like this:
// go run main.go inanç
//
// Then it should output this:
// hi inanç!
// how are you?
// ---------------------------------------------------------
func main() {
// uncomment the code below
// name := "and get the name from the command-line"
// replace and concatenate the `name` variable
// after `hi ` below
msg := `hi CONCATENATE-NAME-VARIABLE-HERE!
how are you?`
fmt.Println(msg)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/03-raw-concat/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
name := os.Args[1]
msg := `hi ` + name + `!
how are you?`
fmt.Println(msg)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/04-count-the-chars/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// ---------------------------------------------------------
// EXERCISE: Count the Chars
//
// 1. Change the following program to work with unicode
// characters.
//
// INPUT
// "İNANÇ"
//
// EXPECTED OUTPUT
// 5
// ---------------------------------------------------------
func main() {
// Currently it returns 7
// Because, it counts the bytes...
// It should count the runes (codepoints) instead.
//
// When you run it with "İNANÇ", it should return 5 not 7.
length := len(os.Args[1])
fmt.Println(length)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/04-count-the-chars/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"unicode/utf8"
)
func main() {
length := utf8.RuneCountInString(os.Args[1])
fmt.Println(length)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/05-improved-banger/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
// ---------------------------------------------------------
// EXERCISE: Improved Banger
//
// Change the Banger program the work with Unicode
// characters.
//
// INPUT
// "İNANÇ"
//
// EXPECTED OUTPUT
// İNANÇ!!!!!
// ---------------------------------------------------------
func main() {
msg := os.Args[1]
s := msg + strings.Repeat("!", len(msg))
fmt.Println(s)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/05-improved-banger/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
"unicode/utf8"
)
func main() {
msg := os.Args[1]
l := utf8.RuneCountInString(msg)
s := msg + strings.Repeat("!", l)
fmt.Println(s)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/06-tolowercase/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: ToLowercase
//
// 1. Look at the documentation of strings package
// 2. Find a function that changes the letters into lowercase
// 3. Get a value from the command-line
// 4. Print the given value in lowercase letters
//
// HINT
// Check out the strings package from Go online documentation.
// You will find the lowercase function there.
//
// INPUT
// "SHEPARD"
//
// EXPECTED OUTPUT
// shepard
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/06-tolowercase/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
func main() {
fmt.Println(strings.ToLower(os.Args[1]))
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/07-trim-it/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// ---------------------------------------------------------
// EXERCISE: Trim It
//
// 1. Look at the documentation of strings package
// 2. Find a function that trims the spaces from
// the given string
// 3. Trim the text variable and print it
//
// EXPECTED OUTPUT
// The weather looks good.
// I should go and play.
// ---------------------------------------------------------
func main() {
msg := `
The weather looks good.
I should go and play.
`
fmt.Println(msg)
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/07-trim-it/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
msg := `
The weather looks good.
I should go and play.
`
fmt.Println(strings.TrimSpace(msg))
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/08-right-trim-it/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// ---------------------------------------------------------
// EXERCISE: Right Trim It
//
// 1. Look at the documentation of strings package
// 2. Find a function that trims the spaces from
// only the right-most part of the given string
// 3. Trim it from the right part only
// 4. Print the number of characters it contains.
//
// RESTRICTION
// Your program should work with unicode string values.
//
// EXPECTED OUTPUT
// 5
// ---------------------------------------------------------
func main() {
// currently it prints 17
// it should print 5
name := "inanç "
fmt.Println(len(name))
}
================================================
FILE: 08-numbers-and-strings/02-strings/exercises/08-right-trim-it/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
"unicode/utf8"
)
func main() {
name := "inanç "
name = strings.TrimRight(name, " ")
l := utf8.RuneCountInString(name)
fmt.Println(l)
}
================================================
FILE: 08-numbers-and-strings/02-strings/questions/questions.md
================================================
## What's the result of this expression?
```go
"\"Hello\\"" + ` \"World\"`
```
1. "Hello" "World"
2. "Hello" \"World\" *CORRECT*
3. "Hello" `"World"`
4. "\"Hello\" `\"World\"`"
> **1:** Go doesn't interpret the escape sequences in raw string literals.
>
> **2:** That's right. Go interprets `\"` as `"` but it doesn't do so for ` \"World\"`.
>
## What's the best way to represent the following text in the code?
```xml
- "Teddy Bear"
```
1. *CORRECT*
```go
`
- "Teddy Bear"
`
```
2.
```go
"
- "Teddy Bear"
"
```
3.
```go
"
- \"Teddy Bear\"
"
```
4.
```go
`
- \"Teddy Bear\"
`
```
> **2-3:** You can't write a string literal like that. It can't be multiple-lines.
>
> **4:** You don't need to use escape sequences inside raw string literals.
>
## What's the result of the following expression?
```go
len("lovely")
```
1. 7
2. 8
3. 6 *CORRECT*
4. 0
> **2:** Remember! "a" is 1 char. `a` is also 1 char.
>
## What's the result of the following expression?
```go
len("very") + len(`\"cool\"`)
```
1. 8
2. 12 *CORRECT*
3. 16
4. 10
> **1:** There are also double-quotes, count them as well.
>
> **2:** That's right. Go doesn't interpreted \" in raw string literals.
>
> **3:** Remember! "very" is 4 characters. `very` is also 4 characters.
>
> **4:** Remember! Go doesn't interpreted \" in raw string literals.
>
## What's the result of the following expression?
```go
len("very") + len("\"cool\"")
```
1. 8
2. 12
3. 16
4. 10 *CORRECT*
> **1:** There are also double-quotes, count them as well.
>
> **2:** Remember! Go interprets escape sequences in string literals.
>
> **4:** That's right. Go does interpret \" in a string literal. So, "\"" means ", which is 1 character.
>
## What's the result of the following expression?
```go
len("péripatéticien")
```
**HINT:** é is 2 bytes long. And, the len function counts the bytes not the letters.
**USELESS INFORMATION:** "péripatéticien" means "wanderer".
1. 14
2. 16 *CORRECT*
3. 18
4. 20
> **1:** Remember! é is 2 bytes long.
>
> **2:** An english letter is 1 byte long. However, é is 2 bytes long. So, that makes up 16 bytes. Cool.
>
> **3:** You didn't count the double-quotes, did you?
>
## How can you find the correct length of the characters in this string literal?
```go
"péripatéticien"
```
1. `len(péripatéticien)`
2. `len("péripatéticien")`
3. `utf8.RuneCountInString("péripatéticien")` *CORRECT*
4. `unicode/utf8.RuneCountInString("péripatéticien")`
> **1:** Where are the double-quotes?
>
> **2:** This only finds the bytes in a string value.
>
> **4:** You're close. But, the package's name is utf8 not unicode/utf8.
>
## What's the result of the following expression?
```go
utf8.RuneCountInString("péripatéticien")
```
1. 16
2. 14 *CORRECT*
3. 18
4. 20
> **1:** This is its byte count. `RuneCountInString` counts the runes (codepoints) not the bytes.
>
> **2:** That's right. `RuneCountInString` returns the number of runes (codepoints) in a string value.
>
## Which package contains string manipulation functions?
1. string
2. unicode/utf8
3. strings *CORRECT*
4. unicode/strings
## What's the result of this expression?
```go
strings.Repeat("*x", 3) + "*"
```
**HINT:** Repeat function repeats the given string.
1. `*x*x*x`
2. `x*x*x`
3. `*x3`
4. `*x*x*x*` *CORRECT*
> **1:** You're close but you missed the concatenation at the end.
>
> **2:** Look closely.
>
> **3:** Wow! You should really watch the lectures again. Sorry.
>
> **4:** That's right. Repeat function repeats the given string. And, the concatenation operator combines the strings.
>
## What's the result of this expression?
```go
strings.ToUpper("bye bye ") + "see you!"
```
1. `bye bye see you!`
2. `BYE BYE SEE YOU!`
3. `bye bye + see you!`
4. `BYE BYE see you!` *CORRECT*
> **1:** You missed the ToUpper?
>
> **2:** You're close but look closely. ToUpper only changes the first part of the string there.
>
> **3:** Not even close. Sorry.
>
> **4:** Perfect! Good catch! ToUpper only changes the first part of the string there.
>
================================================
FILE: 09-go-type-system/01-bits/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
)
func main() {
// %b verb prints bits
// true false, on off, ...
// 1 bit can encode 2 different state: 0 or 1
fmt.Printf("%b\n", 0)
fmt.Printf("%b\n", 1)
// 2 bits can encode 4 different states
// 0 0
// 0 1
// 1 0
// 1 1
// %02b prints 2 bits with leading zeros if any
fmt.Printf("%02b = %d\n", 0, 0)
fmt.Printf("%02b = %d\n", 1, 1)
fmt.Printf("%02b = %d\n", 2, 2)
fmt.Printf("%02b = %d\n", 3, 3)
// run this and analyze:
// how 1 moves from right to the left
// %08b prints 8 bits with leading zeros if any
fmt.Printf("%08b = %d\n", 1, 1)
fmt.Printf("%08b = %d\n", 2, 2)
fmt.Printf("%08b = %d\n", 4, 4)
fmt.Printf("%08b = %d\n", 8, 8)
fmt.Printf("%08b = %d\n", 16, 16)
fmt.Printf("%08b = %d\n", 32, 32)
fmt.Printf("%08b = %d\n", 64, 64)
fmt.Printf("%08b = %d\n", 128, 128)
// ------------------------------------------------
// How to calculate bits?
// ------------------------------------------------
// note: ^ means power of.
// for example: 2^2 means 2 * 2 = 4
// or: 2^3 means 2 * 2 * 2 = 8
// 0 0 0 0 0 0 1 0 is equal to 2 because:
// ^ ^ ^ ^ ^ ^ ^ ^
// | | | | | | | |
// | | | | | | | +-> 2^0 * 0 = 0
// | | | | | | +---> 2^1 * 1 = 2
// | | | | | +-----> 2^2 * 0 = 0
// | | | | +-------> 2^3 * 0 = 0
// | | | +---------> 2^4 * 0 = 0
// | | +-----------> 2^5 * 0 = 0
// | +-------------> 2^6 * 0 = 0
// +---------------> 2^7 * 0 = 0
// ------------+
// 2
i, _ := strconv.ParseInt("00000010", 2, 64)
fmt.Println(i)
// 0 0 0 1 0 1 1 0 is equal to 22 because:
// ^ ^ ^ ^ ^ ^ ^ ^
// | | | | | | | |
// | | | | | | | +-> 2^0 * 0 = 0
// | | | | | | +---> 2^1 * 1 = 2
// | | | | | +-----> 2^2 * 1 = 4
// | | | | +-------> 2^3 * 0 = 0
// | | | +---------> 2^4 * 1 = 16
// | | +-----------> 2^5 * 0 = 0
// | +-------------> 2^6 * 0 = 0
// +---------------> 2^7 * 0 = 0
// ------------+
// 22
i, _ = strconv.ParseInt("00010110", 2, 64)
fmt.Println(i)
}
================================================
FILE: 09-go-type-system/02-bytes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// byte is an integer number with 8 bits (1 byte)
var b byte
// all bits are empty or 0
// this is the minimum number a byte can represent
b = 0
fmt.Printf("%08b = %d\n", b, b)
// all bits are full or 1
// this is the maximum number a byte can represent
b = 255
fmt.Printf("%08b = %d\n", b, b)
}
================================================
FILE: 09-go-type-system/03-predeclared-types/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
"unsafe"
)
func main() {
// you can find the limits of numerics types
// in the math package
fmt.Println("int8 :", math.MinInt8, math.MaxInt8)
fmt.Println("int16 :", math.MinInt16, math.MaxInt16)
fmt.Println("int32 :", math.MinInt32, math.MaxInt32)
fmt.Println("int64 :", math.MinInt64, math.MaxInt64)
// unsigned type can only represent positive integers
fmt.Println("uint8 :", 0, math.MaxUint8)
fmt.Println("uint16 :", 0, math.MaxUint16)
fmt.Println("uint32 :", 0, math.MaxUint32)
fmt.Println("uint64 :", 0, uint64(math.MaxUint64))
// You can't print MaxUint64 directly
// Its size is way bigger for the runtime
// It can only be used in constant expressions
// e means zeros after the number (scientific notation)
// 1e1, is 10 1e2, is 100, 12e1 is 120
fmt.Println("float32:", math.SmallestNonzeroFloat32,
math.MaxFloat32)
fmt.Println("float64:", math.SmallestNonzeroFloat64,
math.MaxFloat64)
// memory costs
fmt.Println("int :", unsafe.Sizeof(int(1)), "bytes")
fmt.Println("int8 :", unsafe.Sizeof(int8(1)), "bytes")
fmt.Println("int16 :", unsafe.Sizeof(int16(1)), "bytes")
fmt.Println("int32 :", unsafe.Sizeof(int32(1)), "bytes")
fmt.Println("int64 :", unsafe.Sizeof(int64(1)), "bytes")
fmt.Println("uint :", unsafe.Sizeof(uint(1)), "bytes")
fmt.Println("uint8 :", unsafe.Sizeof(uint8(1)), "bytes")
fmt.Println("uint16 :", unsafe.Sizeof(uint16(1)), "bytes")
fmt.Println("uint32 :", unsafe.Sizeof(uint32(1)), "bytes")
fmt.Println("uint64 :", unsafe.Sizeof(uint64(1)), "bytes")
fmt.Println("float32:", unsafe.Sizeof(float32(1)), "bytes")
fmt.Println("float64:", unsafe.Sizeof(float64(1)), "bytes")
fmt.Println("hello :", len("hello")+8, "bytes")
fmt.Println("hi :", len("hi")+8, "bytes")
}
================================================
FILE: 09-go-type-system/04-overflow/01-problem/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
width uint8 = 255
height = 255 // int
)
width++
if int(width) < height {
fmt.Println("height is greater")
}
fmt.Printf("width: %d height: %d\n", width, height)
}
================================================
FILE: 09-go-type-system/04-overflow/02-explain/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
)
func main() {
// go catches overflow at compile-time
//
// fmt.Println(int8(math.MaxInt8 + 1)) // overflows
// but it cannot catch them in runtime
var n int8 = math.MaxInt8
// wrap arounds to its negative maximum
fmt.Println("max int8 :", n) // 127
fmt.Println("max int8 + 1 :", n+1) // -128
// wrap arounds to its positive maximum
n = math.MinInt8
fmt.Println("min int8 :", n) // -128
fmt.Println("min int8 - 1 :", n-1) // 127
// wrap arounds to its maximum
var un uint8
fmt.Println("max uint8 :", un) // 0
fmt.Println("max uint8 - 1:", un-1) // 255
// wrap around to its minimum
un = math.MaxUint8
fmt.Println("max uint8 + 1:", un+1) // 0
// floats goes to infinity when overflowed
f := float32(math.MaxFloat32)
fmt.Println("max float :", f*1.2)
}
================================================
FILE: 09-go-type-system/04-overflow/03-destructive/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// uint16 max value is 65535
big := uint16(65535)
// uint8 destroys its value
// to its own max value which is 255
//
// 65535 - 255 is lost.
small := uint8(big)
// fmt.Printf("%b %d\n", big, big)
// fmt.Printf("%b %[1]d\n", big)
fmt.Printf("%016b %[1]d\n", big)
fmt.Printf("%016b %[1]d\n", small)
}
================================================
FILE: 09-go-type-system/05-defined-types/01-duration-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
h, _ := time.ParseDuration("4h30m")
// why would you want to create a new type?
// 1- adding new methods to the type
fmt.Println(h.Hours(), "hours")
// 2- make it a distinct type for type-safety
// you can't use the defined type
// with its underlying type directly.
//
// you need to convert one of them.
var m int64 = 2
h *= time.Duration(m)
fmt.Println(h)
// type of `h` and its underlying type are different
fmt.Printf("Type of h: %T\n", h)
fmt.Printf("Type of h's underlying type: %T\n", int64(h))
}
================================================
FILE: 09-go-type-system/05-defined-types/02-type-definition-create-your-own-type/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// type definitions usually declared at the package level
//
// EXERCISE: Move the declaration into main()'s scope
//
type (
gram float64 // float64 is the underlying type of gram
ounce float64 // float64 is the underlying type of ounce
)
// above code is the same as the following:
// type gram float64
// type ounce float64
func main() {
// type definitions are also allowed in blocks
// underlying types are the same
var g gram = 1000 // gram -> float64
var o ounce // ounce -> float64
// when the underlying types are the same
// then they can be converted between:
// gram, ounce or float64
// afterwards, you'll see also that,
// the important thing is the structure
// of the type. not just its name.
//
// float64 has the real structure, representation,
// and size.
//
// so, it gives the structure to the newly defined type.
// TYPE ERROR: ounce and grams are different types
// o = g * 0.035274
// BUT: They're convertable to each other
o = ounce(g) * 0.035274
fmt.Printf("%g grams is %.2f ounce\n", g, o)
}
================================================
FILE: 09-go-type-system/05-defined-types/03-underlying-types/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"github.com/inancgumus/learngo/09-go-type-system/05-defined-types/03-underlying-types/weights"
)
type (
// Gram underlying type is int
Gram int
// Kilogram underlying type is int
Kilogram Gram
// Ton underlying type is int
Ton Kilogram
)
func main() {
var (
salt Gram = 100
apples Kilogram = 5
truck Ton = 10
)
// types with different names cannot be used together
// salt = apples
// apples = truck
// since their underlying type is int
// they can be converted to any type
// with an underlying type of int
salt = Gram(apples)
apples = Kilogram(truck)
truck = Ton(Kilogram(Gram(int(apples))))
fmt.Printf("salt: %d, apples: %d, truck: %d\n",
salt, apples, truck)
// -----------------------------------------------------
// TYPES FROM DIFFERENT PACKAGES
// -----------------------------------------------------
// Gram and weights.Gram are different types
// You cannot do this
// salt = weights.Gram(100)
// But, you can convert it back to Gram
// Since, their underlying type is int
salt = Gram(weights.Gram(100))
fmt.Printf("Type of weights.Gram: %T\n", weights.Gram(1))
fmt.Printf("Type of main.Gram : %T\n", Gram(1))
// You can declare a new type
// from a type of an external package
type myGram weights.Gram
var pepper myGram = 20
pepper = myGram(salt)
fmt.Printf("Type of pepper : %T\n", pepper)
}
================================================
FILE: 09-go-type-system/05-defined-types/03-underlying-types/weights/weights.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package weights
type (
// Gram underlying type is int64
Gram int
// Kilogram underlying type is int64
Kilogram Gram
// Ton underlying type is int64
Ton Kilogram
)
================================================
FILE: 09-go-type-system/06-aliased-types/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// aliased types are the same types
// just with different names
// for readability and refactoring
var (
// type byte = int8
byteVal byte
uint8Val uint8
intVal int
)
uint8Val = byteVal // ok
var (
// type rune = int32
runeVal rune
int32Val int32
)
runeVal = int32Val // ok
runeVal = rune(int32Val)
runeVal = rune(runeVal)
// keep the compiler happy
_, _, _, _ = byteVal, uint8Val, intVal, runeVal
}
// For the curious - compiler internals:
// https://github.com/golang/go/blob/4f1f503373cda7160392be94e3849b0c9b9ebbda/src/cmd/compile/internal/gc/universe.go#L409
================================================
FILE: 09-go-type-system/exercises/01-optimal-types/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Optimal Types
//
// 1. Choose the optimal data types for the given situations.
// 2. Print them all
// 3. Try converting them to lesser data types.
// For example try converting int64 variable to int32.
// Then observe the result.
// Search the web why the result is so?
//
// NOTE
// This is just an exercise for teaching you different
// data types. Do not apply it to the real-life.
//
// As I said in the lectures that, premature optimization
// is not a good thing.
// ---------------------------------------------------------
func main() {
// DONT FORGET: There are also unsigned data types.
// (For positive numbers)
// DO NOT USE: int data type
// Use only the ones with the bitsizes
// ---
// an english letter (search web for: ascii control code)
// a non-english letter (search web for: unicode codepoint)
// a year in 4 digits like 2040
// a month in 2 digits: 1 to 12
// the speed of the light
// angle of a circle
// PI number: 3.141592653589793
}
================================================
FILE: 09-go-type-system/exercises/01-optimal-types/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// an english letter (search web for: ascii control code)
var letter byte = 'A'
fmt.Println("an english letter:", letter)
// a non-english letter (search web for: unicode codepoint)
var unicode rune
unicode = 'Ç'
fmt.Println("a non-english letter:", unicode)
// a year in 4 digits like 2040
var year uint16 = 2040
fmt.Println("a year in 4 digits like 2040:", year)
// a month in 2 digits: 1 to 12
var month uint8 = 6
fmt.Println("a month in 2 digits: 1 to 12:", month)
// the speed of the light
var lightSpeed uint32 = 670616629 // miles
fmt.Println("the speed of the light:", lightSpeed)
// angle of a circle
var angle float32 = 35.8
fmt.Println("angle of a circle:", angle)
var pi float64
pi = 3.141592653589793
fmt.Println("PI number:", pi)
}
================================================
FILE: 09-go-type-system/exercises/02-the-type-problem/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// ---------------------------------------------------------
// EXERCISE: The Type Problem
//
// Solve the data type problem in the program.
//
// EXPECTED OUTPUT
// width: 265 height: 265
// are they equal? true
// ---------------------------------------------------------
func main() {
// FIX THIS:
// Change the following data types to the correct
// data types where appropriate.
var (
width uint8
height uint16
)
// DONT TOUCH THIS:
width, height = 255, 265
width += 10
fmt.Printf("width: %d height: %d\n", width, height)
// UNCOMMENT THIS:
// fmt.Println("are they equal?", width == height)
}
================================================
FILE: 09-go-type-system/exercises/02-the-type-problem/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
width uint16
height uint16
)
width, height = 255, 265
width += 10
fmt.Printf("width: %d height: %d\n", width, height)
fmt.Println("are they equal?", width == height)
}
================================================
FILE: 09-go-type-system/exercises/03-parse-arg-numbers/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
// ---------------------------------------------------------
// EXERCISE: Parse Arg Numbers
//
// Use strconv.ParseInt function to get int8, int16, and
// int32, and int64 values from command-line.
//
// HINT
// The third argument to ParseInt function represents
// the bitsize.
//
// So, giving it 8 returns an int8 convertable value;
// whereas 16 returns an int16 convertable value.
//
// Please explore the documentation of ParseInt function
// and learn how it works.
//
// EXPECTED OUTPUT
// When runned like this:
// go run main.go 50 25000 2000000 50000000000000000 00000100
//
// It should return this:
// int8 value is : 50
// int16 value is: 25000
// int32 value is: 2000000
// int64 value is: 50000000000000000
// 00000100 is: 4
// ---------------------------------------------------------
func main() {
// --------------------------------------
// EXAMPLE:
// --------------------------------------
// How to get an int8 from command-line:
// First argument should be a value of -128 to 127 range
//
// Second argument: 10 means decimal number
// Third argument : 8 means 8-bits (int8)
val, _ := strconv.ParseInt(os.Args[1], 10, 8)
// Now the val variable is int64 because ParseInt
// returns an int64. But, since I passed 8 as its third
// argument, it returns int8 convertable value.
//
// Try running the program with a value of -128 to 127
// Running it beyond that range will result in
// either -128 or 127.
fmt.Println("int8 value is:", int8(val))
// --------------------------------------
// NOW IT'S YOUR TURN!
// --------------------------------------
// 1. Get an int16 value using ParseInt and convert it and print it
// 2. Get an int32 value using ParseInt and convert it and print it
// 3. Get an int64 value using ParseInt and convert it and print it
// 4. Get an int8 value using ParseInt and convert it and print it
// But this time, get the value in bits.
//
// For example : 00000100
// Should print: 4
}
================================================
FILE: 09-go-type-system/exercises/03-parse-arg-numbers/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// FOR EXAMPLE:
//
// Run this program with 5 arguments like this:
//
// int8 int16 int32 int64 as bits
// go run main.go 50 25000 2000000 5000000000 00000100
// first argument is an int8
val, _ := strconv.ParseInt(os.Args[1], 10, 8)
fmt.Println("int8 value is :", int8(val))
// 2nd argument is an int16
val, _ = strconv.ParseInt(os.Args[2], 10, 16)
fmt.Println("int16 value is:", int16(val))
// 3rd argument is an int32
val, _ = strconv.ParseInt(os.Args[3], 10, 32)
fmt.Println("int32 value is:", int32(val))
// 4th argument is an int64
// Remember ParseInt returns an int64
val, _ = strconv.ParseInt(os.Args[4], 10, 64)
fmt.Println("int64 value is:", val)
// 5th argument is a number in bits. And its int8.
// ParseInt(.., 2, ...) -> 2 means binary base
val, _ = strconv.ParseInt(os.Args[5], 2, 8)
fmt.Printf("%s is: %d\n", os.Args[5], int8(val))
}
================================================
FILE: 09-go-type-system/exercises/04-time-multiplier/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
// ---------------------------------------------------------
// EXERCISE: Time Multiplier
//
// You should get an argument from the command-line and
// you need to multiply the time duration value `t` with
// the given argument.
//
// 1. Get an argument from the command-line
// 2. Convert it to int64 and store it in a variable
// 3. Multiply the `t` variable with that variable
// 4. Print the result
//
// HINT
// You can use ParseInt to convert the command-line
// argument into an int64 value.
//
// You can skip the error value using a blank-identifier.
//
// EXPECTED OUTPUT
//
// When runned like this:
// go run main.go 2
//
// It should print this:
// 3h0m0s
// ---------------------------------------------------------
func main() {
// DONT TOUCH THIS
// 1h30m means: 1 hour 30 minutes
t, _ := time.ParseDuration("1h30m")
// TYPE YOUR CODE HERE
// ....
// DONT TOUCH THIS
fmt.Println(t)
}
================================================
FILE: 09-go-type-system/exercises/04-time-multiplier/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
"time"
)
func main() {
t, _ := time.ParseDuration("1h30m")
// 1. get the first command-line argument
// 2. convert it to int64
multiplier, _ := strconv.ParseInt(os.Args[1], 10, 64)
// 3. multiply the time duration with the given argument
//
// converts the int64 value to time.Duration to be
// able to multiply it with the time.Duration value
t *= time.Duration(multiplier)
// 4. print it
fmt.Println(t)
}
================================================
FILE: 09-go-type-system/exercises/05-refactor-feet-to-meter/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Refactor Feet to Meter
//
// Remember the feet to meters program?
// Now, it's time to refactor it.
// Define your own Feet and Meters types.
//
// Follow the steps inside the code.
// ---------------------------------------------------------
func main() {
// ----------------------------
// 1. Define Feet and Meters types below
// Their underlying type can be float64
// ...
// ----------------------------
// 2. UNCOMMENT THE CODE BELOW THEN DON'T TOUCH IT
// var (
// feet Feet
// meters Meters
// )
// ----------------------------
// 3. Get feet value from the command-line
// 4. Convert it to an float64 first using ParseFloat
// 5. Then, convert it into a Feet type
// ... TYPE YOUR CODE HERE
// ----------------------------
// 6. Uncomment the code below
// 7. And, convert the expression to Meters type
// meters = feet * 0.3048
// ----------------------------
// 8. UNCOMMENT THE CODE BELOW
// fmt.Printf("%g feet is %g meters.\n", feet, meters)
}
================================================
FILE: 09-go-type-system/exercises/05-refactor-feet-to-meter/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// WHY ADDING YOUR OWN TYPES IS IMPORTANT?
//
// 1. Type-Safety
// 2. Increased Readability
// 3. Adding Methods to your Types
type (
Feet float64
Meters float64
)
var (
feet Feet
meters Meters
)
arg := os.Args[1]
// feet is a Feet value now
val, _ := strconv.ParseFloat(arg, 64)
feet = Feet(val)
// meters is a Meters value now
meters = Meters(feet * 0.3048)
fmt.Printf("%g feet is %g meters.\n", feet, meters)
}
================================================
FILE: 09-go-type-system/exercises/06-convert-the-types/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Convert the Types
//
// Convert the variables to appropriate types.
//
// EXPECTED OUTPUT
// 325.5 299.5
// ---------------------------------------------------------
func main() {
// DONT TOUCH THIS:
type (
Temperature float64
Celsius Temperature
Fahrenheit Temperature
)
// DONT TOUCH THIS:
var (
celsius Celsius = 15.5
fahr Fahrenheit = 59.9
celsiusDegree Temperature = 10.5
fahrDegree Temperature = 2.5
factor = 2.
)
// ----------------------------------------
// FIX THE CODE BELOW:
// You should solve it only by using conversions.
// Do not change the code in any other way.
// celsius *= celsiusDegree * factor
// fahr *= fahrDegree * factor
// ----------------------------------------
// DONT TOUCH THIS
fmt.Println(celsius, fahr)
// YOU MAY REMOVE THESE WHEN YOU'RE DONE
_, _, _ = celsiusDegree, fahrDegree, factor
}
================================================
FILE: 09-go-type-system/exercises/06-convert-the-types/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
type (
Temperature float64
Celsius Temperature
Fahrenheit Temperature
)
var (
celsius Celsius = 15.5
fahr Fahrenheit = 59.9
celsiusDegree Temperature = 10.5
fahrDegree Temperature = 2.5
factor = 2.
)
celsius *= Celsius(float64(celsiusDegree) * factor)
fahr *= Fahrenheit(float64(fahrDegree) * factor)
fmt.Println(celsius, fahr)
}
================================================
FILE: 09-go-type-system/exercises/README.md
================================================
# Types
1. **[Find the Optimal Types](https://github.com/inancgumus/learngo/tree/master/09-go-type-system/exercises/01-optimal-types)**
2. **[Fix the Type Problem](https://github.com/inancgumus/learngo/tree/master/09-go-type-system/exercises/02-the-type-problem)**
3. **[Parse Arg Numbers](https://github.com/inancgumus/learngo/tree/master/09-go-type-system/exercises/03-parse-arg-numbers)**
4. **[Time Multiplier](https://github.com/inancgumus/learngo/tree/master/09-go-type-system/exercises/04-time-multiplier)**
5. **[Refactor Feet to Meter](https://github.com/inancgumus/learngo/tree/master/09-go-type-system/exercises/05-refactor-feet-to-meter)**
6. **[Convert the Types](https://github.com/inancgumus/learngo/tree/master/09-go-type-system/exercises/06-convert-the-types)**
================================================
FILE: 09-go-type-system/questions/01-questions-predeclared-types.md
================================================
## Which one is **not** a predeclared data type of Go?
1. int
2. float64
3. uint64
4. uint
5. duration *CORRECT*
6. int8
7. rune
8. byte
9. float32
10. complex128
## What's a predeclared data type?
1. A data type used only in the compiler
2. A built-in data type that comes with Go that you can use it from anywhere without importing any package *CORRECT*
3. The data type of a variable
## By using only 8 bits, how many different numbers or states can you represent?
1. 8
2. 16
3. 256 *CORRECT*
4. 65536
> **3:** 2^8 is 256, so you can represent 256 different states.
>
## How many bits 2 bytes contains?
1. 2
2. 8
3. 16 *CORRECT*
4. 32
5. 64
## What's the output of the following code?
```go
fmt.Printf("%08b = %d", 2, 2)
```
1. 00000001 = 2
2. 00000010 = 2 *CORRECT*
3. 00000100 = 2
4. 00001000 = 2
> EXPLANATION = From right to left, each bit goes from 2^0 to 2^(n - 1).
> **1:** EXPLANATION. Here: 1 is the first digit from the right. So, it is 2^(1 - 1) = 2^0 = 1.
>
> **2:** EXPLANATION. Here: 1 is the second digit from the right. So, it is 2^(2 - 1) = 2^1 = 2.
>
> **3:** EXPLANATION. Here: 1 is the third digit from the right. So, it is 2^(3 - 1) = 2^2 = 4.
>
> **4:** EXPLANATION. Here: 1 is the fourth digit from the right. So, it is 2^(4 - 1) = 2^3 = 8.
>
## How many bytes of memory does an int64 value use?
1. 4
2. 8 *CORRECT*
3. 32
4. 64
> **2:** 1 byte is 8 bits and int64 is 64 bits. So, 64/8=8 bytes.
>
## How many bytes are needed to store a value of uint32 type?
1. 4 *CORRECT*
2. 8
3. 32
4. 64
> **2:** 1 byte is 8 bits and uint32 is 32 bits. So, 32/8=4 bytes.
>
## What's the size of int data type?
1. Depends: 32 bits or 64 bits. *CORRECT*
2. 32 bits
3. 64 bits
> **1:** That's right. Go can change its size at the compile-time depending on which target machine you're compiling your program into.
>
## English letters can be represented by the numbers within the range of: 0-255. For example, 'A' can be 65. Or, 'B' can be 66. So, what's the best data type for storing an English letter?
1. byte *CORRECT*
2. rune
3. int64
4. float64
> **1:** That's right. A byte can represent 0-255 different values. So, it's a great fit for representing English letters, and numbers.
>
> **2:** In practice, you can do it with a rune value. However, rune is 32-bits long and it can store almost every letter in existince. I'm asking for the optimal data type. Try again.
>
> **3:** That would be too large for only 255 different numbers.
>
> **4:** Float is not the best data type for numbers without fractional parts.
>
## What does the following code print?
```go
var letter uint8 = 255
fmt.Print(letter + 5)
```
1. 0
2. 4 *CORRECT*
3. 5
4. 260
> **2:** Unsigned integers wrap around after their maximum capacity. Uint8's max is 255, so, if 255 + 1 is 0, then 255 + 5 is 4.
>
> **3:** You're very close.
>
> **4:** Uint8's max capacity is 255. It can't be 260.
>
## What does the following code print?
```go
var num int8 = -128
fmt.Print(num - 3)
```
1. -131
2. 125 *CORRECT*
3. -125
> **1:** int8's min capacity is -128. It can't be -131.
>
> **2:** Signed integers wrap around after their minimum capacity. int8's min is -128, so, if -128 - 1 is 127, then -128 - 3 is 125.
>
================================================
FILE: 09-go-type-system/questions/02-questions-defined-types.md
================================================
## Why you want to define new types?
1. To declare new methods
2. For type-safety
3. For readability and conveying meaning
4. All of the options above *CORRECT*
> **1-3:** Yes, that's only one of the reasons.
>
## Let's suppose that you've declared the following defined type. Which property below the new type doesn't get from its underlying type?
```go
// For example, let's say that you've defined a new type
// using time.Duration type like this:
type Millennium time.Duration
```
1. Methods *CORRECT*
2. Representation
3. Size
4. Range of values
> **1:** That's right. A defined type doesn't get its source type's methods.
>
> **2-4:** Actually the defined type gets it from its underlying type.
>
## How to define a new type using float32?
1. `var radius float32`
2. `radius = type float32`
3. `type radius float32` *CORRECT*
4. `type radius = float32`
> **1-2:** This is not a correct syntax.
>
> **3:** `radius` is a new type, defined using `float32`.
>
> **4:** This declares `radius` as an alias to `float32`. So, they become the same types.
>
## How to fix the following code?
```go
type Distance int
var (
village Distance = 50
city = 100
)
fmt.Print(village + city)
```
1. `int(village + city)`
2. `village + int(city)`
3. `village(int) + city`
4. `village + Distance(city)` *CORRECT*
> **1-3:** There's a type mismatch in this code. But, this won't fix it.
>
> **4:** That's right. Now, the `city`'s type is Distance in the expression.
>
## For the following program which types you might want to declare?
```go
package main
import "fmt"
func main() {
celsius := 35.
fahrenheit := (9*celsius + 160) / 5
fmt.Printf("%g ºC is %g ºF\n", celsius, fahrenheit)
}
```
1. Celsius and Fahrenheit using int64
2. Celsius and Fahrenheit using float64 *CORRECT*
3. Temperature using int64
4. Temperature using uint32
> **1:** But a degree value has a floating part. So, using an integer may not the best way.
>
> **2:** float64 can represent a degree value.
>
> **3-4:** But a degree value has a floating part. So, using an integer may not the best way. Also, there are two different temperature units here: Celsius and Fahrenheit. Isn't it better to create two distinct types?
>
## What's the underlying type of the Millennium type?
```go
type (
Duration int64
Century Duration
Millennium Century
)
```
1. `int64` *CORRECT*
2. `Duration`
3. `Century`
4. Another type
> **1:** That's right. Go's type system is flat. So, the defined type's underlying type is a type with a real structure. int64 is not just a name, it has its own structure, it's a predeclared type.
>
> **2:** Duration is just a new type name. It doesn't have its own structure.
>
> **3:** Century is just a new type name. It doesn't have its own structure.
>
## Which types do not need to be converted between each other?
**HINT:** Aliased types do not require type conversion.
1. byte and uint8 *CORRECT*
2. byte and rune
3. rune and uint8
4. byte and uint32
> **1:** byte data type is an alias to uint8 data type. So, they don't need conversion between each other. They're the same types.
>
## Which types do not need to be converted between each other?
**HINT:** Aliased types do not require type conversion.
1. byte and uint32
2. byte and rune
3. rune and int32 *CORRECT*
4. byte and int8
> **3:** rune data type is an alias to int32 data type. So, they don't need conversion between each other. They're the same types.
>
================================================
FILE: 10-constants/01-declarations/01-syntax/01-magic-numbers/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// This program uses magic values
func main() {
cm := 100
m := cm / 100 // 100 is a magic value
fmt.Printf("%dcm is %dm\n", cm, m)
cm = 200
m = cm / 100 // 100 is a magic value
fmt.Printf("%dcm is %dm\n", cm, m)
}
================================================
FILE: 10-constants/01-declarations/01-syntax/02-constants/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// This program uses a named constant
// instead of a magic value
func main() {
const meters int = 100
cm := 100
m := cm / meters // using a named constant
fmt.Printf("%dcm is %dm\n", cm, m)
cm = 200
m = cm / meters // using a named constant
fmt.Printf("%dcm is %dm\n", cm, m)
}
================================================
FILE: 10-constants/01-declarations/01-syntax/03-safety/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// Go can't catch the same error at runtime
// When you run this, there will be an error:
//
// panic: runtime error: integer divide by zero
n, m := 1, 0
fmt.Println(n / m)
// Go will detect the division by zero error
// at compile-time
//
// const n int = 1
// const m int = 0
// fmt.Println(n / m)
}
================================================
FILE: 10-constants/01-declarations/01-syntax/04-rules/01-immutability/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
const max int = 100
// ERROR: cannot assign to max
// constants are immutable (cannot change)
// max = 100
}
================================================
FILE: 10-constants/01-declarations/01-syntax/04-rules/02-runtime-func/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
)
func main() {
// math.Pow calculates the power of the given number
fmt.Println(math.Pow10(2)) // 100
fmt.Println(math.Pow10(3)) // 1000
fmt.Println(math.Pow10(4)) // 10000
// ERROR: math.Pow is not a constant
// constants cannot use runtime constructs
// const max int = math.Pow10(2)
}
================================================
FILE: 10-constants/01-declarations/01-syntax/04-rules/03-runtime-var/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
n := 2
// ERROR: n is not a constant
// const max int = n
_ = n
}
================================================
FILE: 10-constants/01-declarations/01-syntax/04-rules/04-len/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// When argument to len is a constant, len can be used
// while initializing a constant
//
// Here, "Hello" is a constant.
const max int = len("Hello")
fmt.Println(max)
}
================================================
FILE: 10-constants/01-declarations/02-constant-types-and-expressions/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const min int = 1
const pi float64 = 3.14
const version string = "2.0.1"
const debug bool = true
const A rune = 'A'
fmt.Println(min, pi, version, debug, A)
}
================================================
FILE: 10-constants/01-declarations/02-constant-types-and-expressions/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const min = 1
const pi = 3.14
const version = "2.0.1"
const debug = true
const A = 'A'
fmt.Println(min, pi, version, debug, A)
}
================================================
FILE: 10-constants/01-declarations/02-constant-types-and-expressions/03/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const min = 1 + 1
const pi = 3.14 * min
const version = "2.0.1" + "-beta"
const debug = !true
const A rune = 'A' + 1
fmt.Println(min, pi, version, debug, A)
}
================================================
FILE: 10-constants/01-declarations/03-multiple-declaration/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// below declaration is the same as this one:
// const (
// min int = 1
// max int = 1000
// )
const min, max int = 1, 1000
fmt.Println(min, max)
// print the types of min and max
fmt.Printf("%T %T\n", min, max)
}
================================================
FILE: 10-constants/01-declarations/03-multiple-declaration/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// constants repeat the previous type and expression
const (
min int = 1
max // int = 1
)
fmt.Println(min, max)
// print the types of min and max
fmt.Printf("%T %T\n", min, max)
}
================================================
FILE: 10-constants/01-declarations/03-multiple-declaration/03/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// constants repeat the previous type and expression
const (
min int = 1 + 1
max // int = 1 + 1
)
fmt.Println(min, max)
// print the types of min and max
fmt.Printf("%T %T\n", min, max)
}
================================================
FILE: 10-constants/02-typeless-constants/01-typeless-constants/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// min and pi are typeless constants
const min = 1 + 1
const pi = 3.14 * min
fmt.Println(min, pi)
}
================================================
FILE: 10-constants/02-typeless-constants/02-typed-vs-typeless/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const min int = 42
var i int
i = min // OK
fmt.Println(i)
}
================================================
FILE: 10-constants/02-typeless-constants/02-typed-vs-typeless/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const min int = 42
var f float64
// ERROR: Type Mismatch
// f = min // NOT OK
fmt.Println(f)
}
================================================
FILE: 10-constants/02-typeless-constants/02-typed-vs-typeless/03/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const min = 42
var f float64
f = min // OK when min is typeless
fmt.Println(f)
}
================================================
FILE: 10-constants/02-typeless-constants/02-typed-vs-typeless/04/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const min = 42
// I've removed int from the below declaration
// since, min's default type is int (you'll learn)
var i = min
var f float64 = min
var b byte = min
var j int32 = min
var r rune = min
// behind the scenes:
// below statement equals to:
//
// var b byte = min
b = byte(min)
fmt.Println(i, f, b, j, r)
}
================================================
FILE: 10-constants/02-typeless-constants/03-default-type/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const min int32 = 1
max := 5 + min
// above line equals to this:
// max := int32(5) + min
fmt.Printf("Type of max: %T\n", max)
}
================================================
FILE: 10-constants/02-typeless-constants/03-default-type/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const min = 1
max := 5 + min
// above line equals to this:
// max := int(5) + int(min)
fmt.Printf("Type of max: %T\n", max)
}
================================================
FILE: 10-constants/02-typeless-constants/03-default-type/03/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
i := 42
f := 3.14
b := true
s := "Hello"
r := 'A'
fmt.Printf("i is %T\n", i)
fmt.Printf("f is %T\n", f)
fmt.Printf("b is %T\n", b)
fmt.Printf("s is %T\n", s)
// int32 = rune (type alias)
fmt.Printf("r is %T\n", r)
}
================================================
FILE: 10-constants/02-typeless-constants/03-default-type/04/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
i := 42 + 3.14 // OK: 42 and 3.14 are typeless
// above line equals to this:
// i := float64(42 + 3.14)
fmt.Printf("i is %T\n", i)
}
================================================
FILE: 10-constants/02-typeless-constants/03-default-type/05/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// NOT OK
// "Hello" string literal cannot be converted
// into a bool value
// f := true + "Hello"
}
================================================
FILE: 10-constants/02-typeless-constants/04-demo/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
type Duration int64
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)
// The types are main.Duration instead of just Duration
// It's because, Duration type now belongs to main func
fmt.Printf("Nanosecond is %T\n", Nanosecond)
fmt.Printf("Microsecond is %T\n", Microsecond)
fmt.Printf("Millisecond is %T\n", Millisecond)
fmt.Printf("Second is %T\n", Second)
fmt.Printf("Minute is %T\n", Minute)
fmt.Printf("Hour is %T\n", Hour)
// Print the types of time.Duration constants directly
// This time, types will be time.Duration
// It's because, they're inside the time package
fmt.Printf("Nanosecond is %T\n", time.Nanosecond)
fmt.Printf("Microsecond is %T\n", time.Microsecond)
fmt.Printf("Millisecond is %T\n", time.Millisecond)
fmt.Printf("Second is %T\n", time.Second)
fmt.Printf("Minute is %T\n", time.Minute)
fmt.Printf("Hour is %T\n", time.Hour)
}
================================================
FILE: 10-constants/02-typeless-constants/04-demo/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
// #1
t := time.Second * 10
fmt.Println(t)
// #2
i := 10
// NOT OK
// time.Duration and int are different types
// t = time.Second * i
// OK: i is int, Duration is int64
// So, i is convertable to int64
t = time.Second * time.Duration(i)
fmt.Println(t)
// #3
const c = 10
// OK: Because, c is typeless
t = time.Second * c
fmt.Println(t)
}
================================================
FILE: 10-constants/03-refactor-feet-to-meters/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
// EXERCISE
//
// This program uses magic numbers
// Refactor it and use named constants instead
func main() {
arg := os.Args[1]
feet, _ := strconv.ParseFloat(arg, 64)
meters := feet * 0.3048
yards := feet * 0.3333
fmt.Printf("%g feet is %g meters.\n", feet, meters)
fmt.Printf("%g feet is %g yards.\n", feet, yards)
}
================================================
FILE: 10-constants/03-refactor-feet-to-meters/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
"os"
"strconv"
)
// This program contains a lot of comments
// Non-commented version is in /without-comments/main.go
func main() {
// You cannot use this syntax.
//
// feetInMeters is declared
// when the declaration completes,
// (at the end of the whole declaration)
//
// And, it's not easy to read
//
// const feetInMeters, feetInYards float64 = 0.3048,
// feetInMeters / 0.9144
const (
feetInMeters = 0.3048
feetInYards = feetInMeters / 0.9144
// cannot call runtime funcs
// feetInYards = math.Round(feetInYards)
)
// Immutable: You cannot assign new values
// feetInYards = 0.333333
arg := os.Args[1]
feet, _ := strconv.ParseFloat(arg, 64)
meters := feet * feetInMeters
yards := math.Round(feet * feetInYards)
fmt.Printf("%g feet is %g meters.\n", feet, meters)
fmt.Printf("%g feet is %g yards.\n", feet, yards)
}
================================================
FILE: 10-constants/03-refactor-feet-to-meters/solution/without-comments/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
"os"
"strconv"
)
// I copied the same program here but without comments.
// So, you can easily read it.
func main() {
const (
feetInMeters float64 = 0.3048
feetInYards = feetInMeters / 0.9144
)
arg := os.Args[1]
feet, _ := strconv.ParseFloat(arg, 64)
meters := feet * feetInMeters
yards := math.Round(feet * feetInYards)
fmt.Printf("%g feet is %g meters.\n", feet, meters)
fmt.Printf("%g feet is %g yards.\n", feet, yards)
}
================================================
FILE: 10-constants/04-iota/01-manually/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
monday = 0
tuesday = 1
wednesday = 2
thursday = 3
friday = 4
saturday = 5
sunday = 6
)
fmt.Println(monday, tuesday, wednesday, thursday, friday,
saturday, sunday)
}
================================================
FILE: 10-constants/04-iota/02-with-iota/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
monday = iota
tuesday
wednesday
thursday
friday
saturday
sunday
)
fmt.Println(monday, tuesday, wednesday, thursday, friday,
saturday, sunday)
}
================================================
FILE: 10-constants/04-iota/03-expressions/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
monday = iota + 1
tuesday
wednesday
thursday
friday
saturday
sunday
)
fmt.Println(monday, tuesday, wednesday, thursday, friday,
saturday, sunday)
}
================================================
FILE: 10-constants/04-iota/04-blank-identifier/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
EST = -5
MST = -7
PST = -8
)
fmt.Println(EST, MST, PST)
}
================================================
FILE: 10-constants/04-iota/04-blank-identifier/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
EST = -(5 + iota) // CORRECT: -5
MST // CORRECT: -6
PST // CORRECT: -7
)
fmt.Println(EST, MST, PST)
}
================================================
FILE: 10-constants/04-iota/04-blank-identifier/03/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
EST = -(5 + iota) // CORRECT: -5
_
MST // CORRECT: -7
PST // CORRECT: -8
)
fmt.Println(EST, MST, PST)
}
================================================
FILE: 10-constants/exercises/01-minutes-in-weeks/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Minutes in Weeks
//
// Calculate how many minutes in two weeks.
//
// STEPS:
// 1. Declare `minsPerDay` constant and initialize it
// to the number of minutes in a day
//
// 2. Declare `weekDays` constant and initialize it
// to 7.
//
// 3. Use printf to print the total number of minutes
// in two weeks.
//
// EXPECTED OUTPUT
// There are 20160 minutes in 2 weeks.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 10-constants/exercises/01-minutes-in-weeks/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
minsPerDay = 60 * 24
weekDays = 7
)
fmt.Printf("There are %d minutes in %d weeks.\n",
minsPerDay*weekDays*2, 2)
}
================================================
FILE: 10-constants/exercises/02-remove-the-magic/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Remove the Magic
//
// Get rid of the magic numbers in the following code.
//
// RESTRICTIONS
// 1. You should declare 3 constants named:
// hoursInDay, daysInWeek, and hoursPerWeek
//
// 2. And, hoursPerWeek constant should be initialized
// using hoursInDay and daysInWeek constants.
//
// EXPECTED OUTPUT
// There are 840 hours in 5 weeks.
// ---------------------------------------------------------
func main() {
fmt.Printf("There are %d hours in %d weeks.\n",
24*7*5, 5)
}
================================================
FILE: 10-constants/exercises/02-remove-the-magic/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
hoursInDay = 24
daysInWeek = 7
hoursPerWeek = hoursInDay * daysInWeek
)
fmt.Printf("There are %d hours in %d weeks.\n",
hoursPerWeek*5, 5)
}
================================================
FILE: 10-constants/exercises/03-constant-length/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Constant Length
//
// Calculate how many characters inside the `home`
// constant and print it.
//
// STEPS:
// 1. Declare a constant named `home`
// 2. Initialize it to "Milky Way Galaxy" string literal
//
// 3. Declare another constant named `length`
// 4. Initialize it by using the built-in function `len`.
//
// 5. Print the message below using the constants that
// you've declared.
//
// RESTRICTION:
// Use Printf.
// Print the `home` constant using the quoted-string verb.
//
// EXPECTED OUTPUT
// There are 16 characters inside "Milky Way Galaxy"
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 10-constants/exercises/03-constant-length/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
home = "Milky Way Galaxy"
length = len(home)
)
fmt.Printf("There are %d characters inside %q\n",
length, home)
}
================================================
FILE: 10-constants/exercises/04-tau/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: TAU
//
// Fix the following program and print the TAU number.
//
// HINT
// You can use %g verb for printing tau.
//
// EXPECTED OUTPUT
// tau = 6.283185307179586
// ---------------------------------------------------------
func main() {
// What's the problem with this code?
// Why it doesn't work?
// const pi, tau = 3.14159265358979323846264, pi * 2
}
================================================
FILE: 10-constants/exercises/04-tau/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
pi = 3.14159265358979323846264
tau = pi * 2
)
fmt.Printf("tau = %g\n", tau)
}
================================================
FILE: 10-constants/exercises/05-area/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Area
//
// Fix the following program.
//
// RESTRICTION
// You should not use any variables.
//
// EXPECTED OUTPUT
// area = 1250
// ---------------------------------------------------------
func main() {
// const (
// width int16 = 25
// height int32 = width * 2
// )
// fmt.Printf("area = %d\n", width*height)
}
================================================
FILE: 10-constants/exercises/05-area/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// Make them typeless
const (
width = 25
height = width * 2
)
fmt.Printf("area = %d\n", width*height)
}
================================================
FILE: 10-constants/exercises/06-no-conversions-allowed/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: No Conversions Allowed
//
// 1. Fix the program without doing any conversion.
// 2. Explain why it doesn't work.
//
// EXPECTED OUTPUT
// 10h0m0s later...
// ---------------------------------------------------------
func main() {
// const later int = 10
// hours, _ := time.ParseDuration("1h")
// fmt.Printf("%s later...\n", hours*later)
}
================================================
FILE: 10-constants/exercises/06-no-conversions-allowed/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
// hours's type is time.Duration
// but later's type was int
// now, `later` is typeless
//
// time.Duration's underlying type is int64
// and, `later` is numeric typeless value
// so, they can be multiplied
const later = 10
hours, _ := time.ParseDuration("1h")
fmt.Printf("%s later...\n", hours*later)
}
================================================
FILE: 10-constants/exercises/07-iota-months/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Iota Months
//
// 1. Initialize the constants using iota.
// 2. You should find the correct formula for iota.
//
// RESTRICTIONS
// 1. Remove the initializer values from all constants.
// 2. Then use iota once for initializing one of the
// constants.
//
// EXPECTED OUTPUT
// 9 10 11
// ---------------------------------------------------------
func main() {
const (
Nov = 11
Oct = 10
Sep = 9
)
fmt.Println(Sep, Oct, Nov)
}
================================================
FILE: 10-constants/exercises/07-iota-months/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
Nov = 11 - iota // 11 - 0 = 11
Oct // 11 - 1 = 10
Sep // 11 - 2 = 9
)
fmt.Println(Sep, Oct, Nov)
}
================================================
FILE: 10-constants/exercises/08-iota-months-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Iota Months #2
//
// 1. Initialize multiple constants using iota.
// 2. Please follow the instructions inside the code.
//
// EXPECTED OUTPUT
// 1 2 3
// ---------------------------------------------------------
func main() {
// HINT: This is a valid constant declaration
// Blank-Identifier can be used in place of a name
const _ = iota
// ^- this is just a name
// Now, use iota and initialize the following constants
// "automatically" to 1, 2, and 3 respectively.
const (
Jan = iota
Feb
Mar
)
// This should print: 1 2 3
// Not: 0 1 2
fmt.Println(Jan, Feb, Mar)
}
================================================
FILE: 10-constants/exercises/08-iota-months-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
_ = iota // 0
Jan // 1
Feb // 2
Mar // 3
)
fmt.Println(Jan, Feb, Mar)
}
================================================
FILE: 10-constants/exercises/09-iota-seasons/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Iota Seasons
//
// Use iota to initialize the season constants.
//
// HINT
// You can change the order of the constants.
//
// EXPECTED OUTPUT
// 12 3 6 9
// ---------------------------------------------------------
func main() {
// NOTE : You should remove all the initializers below
// first. Then use iota to fix it.
const (
Winter = 12
Spring = 3
Summer = 6
Fall = 9
)
fmt.Println(Winter, Spring, Summer, Fall)
}
================================================
FILE: 10-constants/exercises/09-iota-seasons/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const (
Spring = (iota + 1) * 3
Summer
Fall
Winter
)
fmt.Println(Winter, Spring, Summer, Fall)
}
================================================
FILE: 10-constants/exercises/README.md
================================================
# Constants
1. **[Minutes in Weeks](https://github.com/inancgumus/learngo/tree/master/10-constants/exercises/01-minutes-in-weeks)**
2. **[Remove the Magic](https://github.com/inancgumus/learngo/tree/master/10-constants/exercises/02-remove-the-magic)**
3. **[Constant Length](https://github.com/inancgumus/learngo/tree/master/10-constants/exercises/03-constant-length)**
4. **[TAU](https://github.com/inancgumus/learngo/tree/master/10-constants/exercises/04-tau)**
5. **[Area](https://github.com/inancgumus/learngo/tree/master/10-constants/exercises/05-area)**
6. **[No Conversions Allowed](https://github.com/inancgumus/learngo/tree/master/10-constants/exercises/06-no-conversions-allowed)**
7. **[Iota Months](https://github.com/inancgumus/learngo/tree/master/10-constants/exercises/07-iota-months)**
8. **[Iota Months #2](https://github.com/inancgumus/learngo/tree/master/10-constants/exercises/08-iota-months-2)**
9. **[Iota Seasons](https://github.com/inancgumus/learngo/tree/master/10-constants/exercises/09-iota-seasons)**
================================================
FILE: 10-constants/questions/questions.md
================================================
## What's a magic value?
1. A value which pops up from somewhere
2. Merlin the Wizard's spell
3. An unnamed constant value in the source code *CORRECT*
4. A named constant
## What's a named constant?
1. A constant with a cool name
2. A constant value declared with a name *CORRECT*
3. A literal value converted to a name
## How to declare a constant?
1. `Const version int = 3`
2. `const version int := 3`
2. `const version int = 3` *CORRECT*
> **1:** "C"onst should be just "c"onst.
>
## Which code below is correct?
1. `s := "pick me"; const length = len(s)`
2. `const message = "pick me!"; const length = len(message)` *CORRECT*
3. `const length = utf8.RuneCountInString("pick me")`
> **1:** `s` not a constant.
>
> **2:** `len` function can be used as an initial value to a constant, when the argument to `len` is also a constant.
>
> **3:** You cannot call functions while initializing a constant.
>
## Which explanation below is correct for the following code?
```go
const speed = 100
porsche := speed * 3
```
1. speed is typeless and porsche's type is int *CORRECT*
2. speed's type is int and porsche's type is also int
3. speed and porsche are typeless
> **2:** speed has no type.
>
> **3:** A variable cannot be typeless.
>
## How to fix the following code?
```go
const spell string
spell = "Abracadabra"
```
1. `const spell = "Abracadabra"` *CORRECT*
2. `spell := "Abracadabra"`
3. `var spell = "Abracadabra"`
> **1:** A constant always have to be initialized to a value. And, sometimes the type declaration is not necessary.
>
> **2-3:** That's a variable not a constant.
>
## How to fix the following code?
```go
const total int8 = 10
x := 5
fmt.Print(total * x)
```
```go
// #1 - *CORRECT*
const total = 10
x := 5
fmt.Print(total * x)
// #2
const total int64 = 10
x := 5
fmt.Print(total * x)
// #3
const total int64 = 10
x := 5
fmt.Print(int64(total) * x)
```
> **1:** Now, the total constant is typeless, so it can be used with the x variable.
>
> **2:** There's still a type mismatch. x is int not int64.
>
> **3:** total is already int64. No need to convert it again.
>
## What are the values of the following constants?
```go
const (
Yes = (iota * 5) + 2
No
Both
)
```
1. Yes=0 No=1 Both=2
2. Yes=2 No=3 Both=4
3. Yes=7 No=12 Both=17
4. Yes=2 No=7 Both=12 *CORRECT*
> **3:** iota starts at 0, not 1.
>
================================================
FILE: 11-if/01-boolean-operators/01-comparison-operators/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
speed := 100 // #1
// speed := 10 // #2
fast := speed >= 80
slow := speed < 20
fmt.Printf("fast's type is %T\n", fast)
fmt.Printf("going fast? %t\n", fast)
fmt.Printf("going slow? %t\n", slow)
fmt.Printf("is it 100 mph? %t\n", speed == 100)
fmt.Printf("is it not 100 mph? %t\n", speed != 100)
}
================================================
FILE: 11-if/01-boolean-operators/02-comparison-and-assignability/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
var speed int
// speed = "100" // NOT OK
var running bool
// running = 50 // NOT OK
var force float64
// speed = force // NOT OK
_, _, _ = speed, running, force
}
================================================
FILE: 11-if/01-boolean-operators/02-comparison-and-assignability/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
var speed int
speed = 50 // OK
var running bool
running = true // OK
var force float64
speed = int(force)
_, _, _ = speed, running, force
}
================================================
FILE: 11-if/01-boolean-operators/02-comparison-and-assignability/03/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
speed := 100 // #1
// speed := 10 // #2
fast := speed >= 80
slow := speed < 20
fmt.Printf("going fast? %t\n", fast)
fmt.Printf("going slow? %t\n", slow)
fmt.Printf("is it 100 mph? %t\n", speed == 100)
fmt.Printf("is it not 100 mph? %t\n", speed != 100)
fmt.Println(strings.Repeat("-", 25))
// -------------------------
// #3
speedB := 150.5
faster := speedB > 100 // ok: untyped
fmt.Println("is the other car going faster?", faster)
// ERROR: Type Mismatch
// faster = speedB > speed
faster = speedB > float64(speed)
fmt.Println("is the other car going faster?", faster)
// #4
// ERROR:
// only numeric values are comparable with
// ordering operators: <, <=, >, >=
// fmt.Println(true > faster)
}
================================================
FILE: 11-if/01-boolean-operators/03-logical-operators/01-and-operator/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// remove the comments and run
// I've commented the lines it's because of the warnings
// fmt.Println("true && true =", true && true)
fmt.Println("true && false =", true && false)
fmt.Println("false && true =", false && true)
// fmt.Println("false && false =", false && false)
}
================================================
FILE: 11-if/01-boolean-operators/03-logical-operators/01-and-operator/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
speed := 100
fmt.Println("within limits?",
speed >= 40 && speed <= 55,
)
speed = 20
fmt.Println("within limits?",
speed >= 40 && speed <= 55,
// ^- short-circuits in the first expression here
// because, it becomes false
)
speed = 50
fmt.Println("within limits?",
speed >= 40 && speed <= 55,
)
// ERROR: invalid
// both operands should be booleans
// 1 && 2
fmt.Println(1 == 1 && 2 == 2)
}
================================================
FILE: 11-if/01-boolean-operators/03-logical-operators/02-or-operator/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// remove the comments and run
// I've commented the lines it's because of the warnings
// fmt.Println("true || true =", true || true)
fmt.Println("true || false =", true || false)
fmt.Println("false || true =", false || true)
// fmt.Println("false || false =", false || false)
}
================================================
FILE: 11-if/01-boolean-operators/03-logical-operators/02-or-operator/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
color := "red"
fmt.Println("reddish colors?",
// true || false => true (short-circuits)
color == "red" || color == "dark red",
)
color = "dark red"
fmt.Println("reddish colors?",
// false || true => true
color == "red" || color == "dark red",
)
fmt.Println("greenish colors?",
// false || false => false
color == "green" || color == "light green",
)
}
================================================
FILE: 11-if/01-boolean-operators/03-logical-operators/03-not-operator/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println(
"hi" == "hi" && 3 > 2, // true && true => true
"hi" != "hi" || 3 > 2, // false || true => true
!("hi" != "hi" || 3 > 2), // !(false || true) => false
)
}
================================================
FILE: 11-if/01-boolean-operators/03-logical-operators/03-not-operator/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var on bool
on = !on
fmt.Println(on)
on = !!on
fmt.Println(on)
}
================================================
FILE: 11-if/02-if-statement/01-if-branch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
score, valid := 5, true
if score > 3 && valid {
fmt.Println("good")
}
}
================================================
FILE: 11-if/02-if-statement/02-else-branch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
score, valid := 3, true
if score > 3 && valid {
fmt.Println("good")
} else {
fmt.Println("low")
}
}
================================================
FILE: 11-if/02-if-statement/03-else-if-branch/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
score := 3
if score > 3 {
fmt.Println("good")
} else if score == 3 {
fmt.Println("on the edge")
} else {
fmt.Println("low")
}
}
================================================
FILE: 11-if/02-if-statement/03-else-if-branch/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
score := 2
if score > 3 {
fmt.Println("good")
} else if score == 3 {
fmt.Println("on the edge")
} else if score == 2 {
fmt.Println("meh...")
} else {
fmt.Println("low")
}
}
================================================
FILE: 11-if/02-if-statement/04-refactor-feet-to-meters/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
const usage = `
Feet to Meters
--------------
This program converts feet into meters.
Usage:
feet [feetsToConvert]`
func main() {
if len(os.Args) < 2 {
fmt.Println(strings.TrimSpace(usage))
// ALTERNATIVE:
// fmt.Println("Please tell me a value in feet")
return
}
arg := os.Args[1]
feet, _ := strconv.ParseFloat(arg, 64)
meters := feet * 0.3048
fmt.Printf("%g feet is %g meters.\n", feet, meters)
}
================================================
FILE: 11-if/02-if-statement/05-challenge-userpass/01-1st-challenge/01-challenge/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// CHALLENGE #1
// Create a user/password protected program.
//
// EXAMPLE USER
// username: jack
// password: 1888
//
// EXPECTED OUTPUT
// go run main.go
// Usage: [username] [password]
//
// go run main.go albert
// Usage: [username] [password]
//
// go run main.go hacker 42
// Access denied for "hacker".
//
// go run main.go jack 6475
// Invalid password for "jack".
//
// go run main.go jack 1888
// Access granted to "jack".
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 11-if/02-if-statement/05-challenge-userpass/01-1st-challenge/02-solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
args := os.Args
if len(args) != 3 {
fmt.Println("Usage: [username] [password]")
return
}
u, p := args[1], args[2]
if u != "jack" {
fmt.Printf("Access denied for %q.\n", u)
} else if p != "1888" {
fmt.Printf("Invalid password for %q.\n", u)
} else {
fmt.Printf("Access granted to %q.\n", u)
}
}
================================================
FILE: 11-if/02-if-statement/05-challenge-userpass/01-1st-challenge/03-solution-refactor/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
const (
usage = "Usage: [username] [password]"
errUser = "Access denied for %q.\n"
errPwd = "Invalid password for %q.\n"
accessOK = "Access granted to %q.\n"
user = "jack"
pass = "1888"
)
func main() {
args := os.Args
if len(args) != 3 {
fmt.Println(usage)
return
}
u, p := args[1], args[2]
if u != user {
fmt.Printf(errUser, u)
} else if p != pass {
fmt.Printf(errPwd, u)
} else {
fmt.Printf(accessOK, u)
}
}
================================================
FILE: 11-if/02-if-statement/05-challenge-userpass/02-2nd-challenge/01-challenge/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// ---------------------------------------------------------
// CHALLENGE #2
// Add one more user to the PassMe program below.
//
// EXAMPLE USERS
// username: jack
// password: 1888
//
// username: inanc
// password: 1879
//
// EXPECTED OUTPUT
// go run main.go
// Usage: [username] [password]
//
// go run main.go hacker 42
// Access denied for "hacker".
//
// go run main.go jack 1888
// Access granted to "jack".
//
// go run main.go inanc 1879
// Access granted to "inanc".
//
// go run main.go jack 1879
// Invalid password for "jack".
//
// go run main.go inanc 1888
// Invalid password for "inanc".
// ---------------------------------------------------------
const (
usage = "Usage: [username] [password]"
errUser = "Access denied for %q.\n"
errPwd = "Invalid password for %q.\n"
accessOK = "Access granted to %q.\n"
user = "jack"
pass = "1888"
)
func main() {
args := os.Args
if len(args) != 3 {
fmt.Println(usage)
return
}
u, p := args[1], args[2]
if u != user {
fmt.Printf(errUser, u)
} else if p != pass {
fmt.Printf(errPwd, u)
} else {
fmt.Printf(accessOK, u)
}
}
================================================
FILE: 11-if/02-if-statement/05-challenge-userpass/02-2nd-challenge/02-solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
const (
usage = "Usage: [username] [password]"
errUser = "Access denied for %q.\n"
errPwd = "Invalid password for %q.\n"
accessOK = "Access granted to %q.\n"
user, user2 = "jack", "inanc"
pass, pass2 = "1888", "1879"
)
func main() {
args := os.Args
if len(args) != 3 {
fmt.Println(usage)
return
}
u, p := args[1], args[2]
if u != user && u != user2 {
fmt.Printf(errUser, u)
} else if u == user && p == pass {
fmt.Printf(accessOK, u)
} else if u == user2 && p == pass2 {
fmt.Printf(accessOK, u)
} else {
fmt.Printf(errPwd, u)
}
}
================================================
FILE: 11-if/03-error-handling/01-itoa/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
)
func main() {
// Itoa doesn't return any errors
// So, you don't have to handle the errors for it
s := strconv.Itoa(42)
fmt.Println(s)
}
================================================
FILE: 11-if/03-error-handling/02-atoi/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// Atoi returns an error value
// So, you should always check it
n, err := strconv.Atoi(os.Args[1])
fmt.Println("Converted number :", n)
fmt.Println("Returned error value:", err)
}
================================================
FILE: 11-if/03-error-handling/03-atoi-error-handling/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
age := os.Args[1]
// Atoi returns an int and an error value
// So, you need to handle the errors
n, err := strconv.Atoi(age)
// handle the error immediately and quit
// don't do anything else here
if err != nil {
fmt.Println("ERROR:", err)
// quits/returns from the main function
// so, the program ends
return
}
// DO NOT DO THIS:
// else {
// happy path
// }
// DO THIS:
// happy path (err is nil)
fmt.Printf("SUCCESS: Converted %q to %d.\n", age, n)
}
================================================
FILE: 11-if/03-error-handling/04-challenge-feet-to-meters/01-challenge/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
// ---------------------------------------------------------
// CHALLENGE
// Add error handling to the feet to meters program.
//
// EXPECTED OUTPUT
// go run main.go hello
// error: 'hello' is not a number.
//
// go run main.go what
// error: 'what' is not a number.
//
// go run main.go 100
// 100 feet is 30.48 meters.
// ---------------------------------------------------------
const usage = `
Feet to Meters
--------------
This program converts feet into meters.
Usage:
feet [feetsToConvert]`
func main() {
if len(os.Args) < 2 {
fmt.Println(strings.TrimSpace(usage))
return
}
arg := os.Args[1]
feet, _ := strconv.ParseFloat(arg, 64)
meters := feet * 0.3048
fmt.Printf("%g feet is %g meters.\n", feet, meters)
}
================================================
FILE: 11-if/03-error-handling/04-challenge-feet-to-meters/02-solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
const usage = `
Feet to Meters
--------------
This program converts feet into meters.
Usage:
feet [feetsToConvert]`
func main() {
if len(os.Args) < 2 {
fmt.Println(strings.TrimSpace(usage))
return
}
arg := os.Args[1]
feet, err := strconv.ParseFloat(arg, 64)
if err != nil {
fmt.Printf("error: '%s' is not a number.\n", arg)
return
}
meters := feet * 0.3048
fmt.Printf("%g feet is %g meters.\n", feet, meters)
}
================================================
FILE: 11-if/04-short-if/01-without-short-if/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
)
func main() {
n, err := strconv.Atoi("42")
if err == nil {
fmt.Println("There was no error, n is", n)
}
}
================================================
FILE: 11-if/04-short-if/02-with-short-if/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
)
func main() {
if n, err := strconv.Atoi("42"); err == nil {
// n and err are available here
fmt.Println("There was no error, n is", n)
}
// n and err are not available here
// fmt.Println(n, err)
}
================================================
FILE: 11-if/04-short-if/03-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if a := os.Args; len(a) != 2 {
// only a is available here
fmt.Println("Give me a number.")
// no need to return on error
// return
} else if n, err := strconv.Atoi(a[1]); err != nil {
// a, n and err are available here
fmt.Printf("Cannot convert %q.\n", a[1])
// no need to return on error
// return
} else {
// all of the variables (names)
// are available here
fmt.Printf("%s * 2 is %d\n", a[1], n*2)
}
// a, n and err are not available here
// they belong to the if statement
// TRY:
// fmt.Println(a, n, err)
}
================================================
FILE: 11-if/04-short-if/04-scope-shadowing/01-shadowing/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// UNCOMMENT THIS TO SEE IT IN ACTION:
// var n int
if a := os.Args; len(a) != 2 {
fmt.Println("Give me a number.")
} else if n, err := strconv.Atoi(a[1]); err != nil {
// else if here shadows the main func's n
// variable and it declares it own
// with the same name: n
fmt.Printf("Cannot convert %q.\n", a[1])
} else {
fmt.Printf("%s * 2 is %d\n", a[1], n*2)
}
// n here belongs to the main func
// not to the if statement above
// UNCOMMENT ALSO LINES BELOW TO SEE IT IN ACTION:
// fmt.Printf("n is %d. 👻 👻 👻 - you've been shadowed ;-)\n", n)
}
================================================
FILE: 11-if/04-short-if/04-scope-shadowing/02-shadowing-solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// n and err belongs to the main function now
// not only to the if statement below
var (
n int
err error
)
if a := os.Args; len(a) != 2 {
fmt.Println("Give me a number.")
} else if n, err = strconv.Atoi(a[1]); err != nil {
// here else if uses the main func's n and err
// variables instead of its own
fmt.Printf("Cannot convert %q.\n", a[1])
} else {
// assigns the result back into main func's
// n variable
n *= 2
fmt.Printf("%s * 2 is %d\n", a[1], n)
}
// if statement has calculated the result using
// the main func's n variable
//
// so, that's why it prints the correct result here
fmt.Println("n is", n)
}
================================================
FILE: 11-if/exercises/01-age-seasons/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Age Seasons
//
// Let's start simple. Print the expected outputs,
// depending on the age variable.
//
// EXPECTED OUTPUT
// If age is greater than 60, print:
// Getting older
// If age is greater than 30, print:
// Getting wiser
// If age is greater than 20, print:
// Adulthood
// If age is greater than 10, print:
// Young blood
// Otherwise, print:
// Booting up
// ---------------------------------------------------------
func main() {
// Change this accordingly to produce the expected outputs
// age := 10
// Type your if statement here.
}
================================================
FILE: 11-if/exercises/01-age-seasons/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
age := 10
if age > 60 {
fmt.Println("Getting older")
} else if age > 30 {
fmt.Println("Getting wiser")
} else if age > 20 {
fmt.Println("Adulthood")
} else if age > 10 {
fmt.Println("Young blood")
} else {
fmt.Println("Booting up")
}
}
================================================
FILE: 11-if/exercises/02-simplify-it/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Simplify It
//
// Can you simplify the if statement inside the code below?
//
// When:
// isSphere == true and
// radius is equal or greater than 200
//
// It will print "It's a big sphere."
//
// Otherwise, it will print "I don't know."
//
// EXPECTED OUTPUT
// It's a big sphere.
// ---------------------------------------------------------
func main() {
// DO NOT TOUCH THIS
isSphere, radius := true, 200
var big bool
if radius >= 50 {
if radius >= 100 {
if radius >= 200 {
big = true
}
}
}
if big != true {
fmt.Println("I don't know.")
} else if !(isSphere == false) {
fmt.Println("It's a big sphere.")
} else {
fmt.Println("I don't know.")
}
}
================================================
FILE: 11-if/exercises/02-simplify-it/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
isSphere, radius := true, 200
if isSphere && radius >= 200 {
fmt.Println("It's a big sphere.")
} else {
fmt.Println("I don't know.")
}
}
================================================
FILE: 11-if/exercises/03-arg-count/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Arg Count
//
// 1. Get arguments from command-line.
// 2. Print the expected outputs below depending on the number
// of arguments.
//
// EXPECTED OUTPUT
// go run main.go
// Give me args
//
// go run main.go hello
// There is one: "hello"
//
// go run main.go hi there
// There are two: "hi there"
//
// go run main.go I wanna be a gopher
// There are 5 arguments
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 11-if/exercises/03-arg-count/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
var (
args = os.Args
l = len(args) - 1
)
if l == 0 {
fmt.Println("Give me args")
} else if l == 1 {
fmt.Printf("There is one: %q\n", args[1])
} else if l == 2 {
fmt.Printf(
`There are two: "%s %s"`+"\n",
args[1], args[2],
)
} else {
fmt.Printf("There are %d arguments\n", l)
}
}
================================================
FILE: 11-if/exercises/04-vowel-or-cons/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Vowel or Consonant
//
// Detect whether a letter is vowel or consonant.
//
// NOTE
// y or w is called a semi-vowel.
// Check out: https://www.merriam-webster.com/words-at-play/why-y-is-sometimes-a-vowel-usage
// Check out: https://www.dictionary.com/e/w-vowel/
//
// HINT
// + You can find the length of an argument using the len function.
//
// + len(os.Args[1]) will give you the length of the 1st argument.
//
// BONUS
// Use strings.IndexAny function to detect the vowels.
// Search on Google for: golang pkg strings IndexAny
//
// Furthermore, you can also use strings.ContainsAny. Check out: https://golang.org/pkg/strings/#ContainsAny
//
// EXPECTED OUTPUT
// go run main.go
// Give me a letter
//
// go run main.go hey
// Give me a letter
//
// go run main.go a
// "a" is a vowel.
//
// go run main.go y
// "y" is sometimes a vowel, sometimes not.
//
// go run main.go w
// "w" is sometimes a vowel, sometimes not.
//
// go run main.go x
// "x" is a consonant.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 11-if/exercises/04-vowel-or-cons/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
args := os.Args
if len(args) != 2 || len(args[1]) != 1 {
fmt.Println("Give me a letter")
return
}
// I didn't use a short-if here because, it's already
// hard to read. Do not make it harder.
s := args[1]
if s == "a" || s == "e" || s == "i" || s == "o" || s == "u" {
fmt.Printf("%q is a vowel.\n", s)
} else if s == "w" || s == "y" {
fmt.Printf("%q is sometimes a vowel, sometimes not.\n", s)
} else {
fmt.Printf("%q is a consonant.\n", s)
}
}
================================================
FILE: 11-if/exercises/04-vowel-or-cons/solution2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
func main() {
args := os.Args
if len(args) != 2 || len(args[1]) != 1 {
fmt.Println("Give me a letter")
return
}
s := args[1]
if strings.IndexAny(s, "aeiou") != -1 {
fmt.Printf("%q is a vowel.\n", s)
} else if s == "w" || s == "y" {
fmt.Printf("%q is sometimes a vowel, sometimes not.\n", s)
} else {
fmt.Printf("%q is a consonant.\n", s)
}
// Notice that:
//
// I didn't use IndexAny for the else if above.
//
// It's because, calling a function is a costly operation.
// And, this way, the code is simpler.
}
================================================
FILE: 11-if/exercises/05-movie-ratings/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// STORY
//
// Your boss wants you to create a program that will check
// whether a person can watch a particular movie or not.
//
// Imagine that another program provides the age to your
// program. Depending on what you return, the other program
// will issue the tickets to the person automatically.
//
// EXERCISE: Movie Ratings
//
// 1. Get the age from the command-line.
//
// 2. Return one of the following messages if the age is:
// -> Above 17 : "R-Rated"
// -> Between 13 and 17: "PG-13"
// -> Below 13 : "PG-Rated"
//
// RESTRICTIONS:
// 1. If age data is wrong or absent let the user know.
// 2. Do not accept negative age.
//
// BONUS:
// 1. BONUS: Use if statements only twice throughout your program.
// 2. BONUS: Use an if statement only once.
//
// EXPECTED OUTPUT
// go run main.go 18
// R-Rated
//
// go run main.go 17
// PG-13
//
// go run main.go 12
// PG-Rated
//
// go run main.go
// Requires age
//
// go run main.go -5
// Wrong age: "-5"
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 11-if/exercises/05-movie-ratings/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) != 2 {
fmt.Println("Requires age")
return
}
age, err := strconv.Atoi(os.Args[1])
if err != nil || age < 0 {
fmt.Printf(`Wrong age: %q`+"\n", os.Args[1])
return
} else if age > 17 {
fmt.Println("R-Rated")
} else if age >= 13 && age <= 17 {
fmt.Println("PG-13")
} else if age < 13 {
fmt.Println("PG-Rated")
}
}
================================================
FILE: 11-if/exercises/05-movie-ratings/solution2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
// 🛑 DON'T DO THIS:
// It's hard to read.
// It's just an exercise.
func main() {
if len(os.Args) != 2 {
fmt.Println("Requires age")
return
} else if age, err := strconv.Atoi(os.Args[1]); err != nil || age < 0 {
fmt.Printf(`Wrong age: %q`+"\n", os.Args[1])
return
} else if age > 17 {
fmt.Println("R-Rated")
} else if age >= 13 && age <= 17 {
fmt.Println("PG-13")
} else if age < 13 {
fmt.Println("PG-Rated")
}
}
================================================
FILE: 11-if/exercises/06-odd-even/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Odd or Even
//
// 1. Get a number from the command-line.
//
// 2. Find whether the number is odd, even and divisible by 8.
//
// RESTRICTION
// Handle the error. If the number is not a valid number,
// or it's not provided, let the user know.
//
// EXPECTED OUTPUT
// go run main.go 16
// 16 is an even number and it's divisible by 8
//
// go run main.go 4
// 4 is an even number
//
// go run main.go 3
// 3 is an odd number
//
// go run main.go
// Pick a number
//
// go run main.go ABC
// "ABC" is not a number
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 11-if/exercises/06-odd-even/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) != 2 {
fmt.Println("Pick a number")
return
}
n, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Printf("%q is not a number\n", os.Args[1])
return
}
if n%8 == 0 {
fmt.Printf("%d is an even number and it's divisible by 8\n", n)
} else if n%2 == 0 {
fmt.Printf("%d is an even number\n", n)
} else {
fmt.Printf("%d is an odd number\n", n)
}
}
================================================
FILE: 11-if/exercises/07-leap-year/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Leap Year
//
// Find out whether a given year is a leap year or not.
//
// EXPECTED OUTPUT
// go run main.go
// Give me a year number
//
// go run main.go eighties
// "eighties" is not a valid year.
//
// go run main.go 2018
// 2018 is not a leap year.
//
// go run main.go 2100
// 2100 is not a leap year.
//
// go run main.go 2019
// 2019 is not a leap year.
//
// go run main.go 2020
// 2020 is a leap year.
//
// go run main.go 2024
// 2024 is a leap year.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 11-if/exercises/07-leap-year/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) != 2 {
fmt.Println("Give me a year number")
return
}
year, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Printf("%q is not a valid year.\n", os.Args[1])
return
}
// Notice that:
// I've intentionally created this solution as verbose
// as I can.
//
// See the next exercise.
var leap bool
if year%400 == 0 {
leap = true
} else if year%100 == 0 {
leap = false
} else if year%4 == 0 {
leap = true
}
if leap {
fmt.Printf("%d is a leap year.\n", year)
} else {
fmt.Printf("%d is not a leap year.\n", year)
}
}
================================================
FILE: 11-if/exercises/08-simplify-leap-year/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Simplify the Leap Year
//
// 1. Look at the solution of "the previous exercise".
//
// 2. And simplify the code (especially the if statements!).
//
// EXPECTED OUTPUT
// It's the same as the previous exercise.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 11-if/exercises/08-simplify-leap-year/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) != 2 {
fmt.Println("Give me a year number")
return
}
year, err := strconv.Atoi(os.Args[1])
if err != nil {
fmt.Printf("%q is not a valid year.\n", os.Args[1])
return
}
if year%4 == 0 && (year%100 != 0 || year%400 == 0) {
fmt.Printf("%d is a leap year.\n", year)
} else {
fmt.Printf("%d is not a leap year.\n", year)
}
}
// Review the original source code here:
// https://github.com/golang/go/blob/ad644d2e86bab85787879d41c2d2aebbd7c57db8/src/time/time.go#L1289
================================================
FILE: 11-if/exercises/09-days-in-month/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Days in a Month
//
// Print the number of days in a given month.
//
// RESTRICTIONS
// 1. On a leap year, february should print 29. Otherwise, 28.
//
// Set your computer clock to 2020 to see whether it works.
//
// 2. It should work case-insensitive. See below.
//
// Search on Google: golang pkg strings ToLower
//
// 3. Get the current year using the time.Now()
//
// Search on Google: golang pkg time now year
//
//
// EXPECTED OUTPUT
//
// -----------------------------------------
// Your solution should not accept invalid months
// -----------------------------------------
// go run main.go
// Give me a month name
//
// go run main.go sheep
// "sheep" is not a month.
//
// -----------------------------------------
// Your solution should handle the leap years
// -----------------------------------------
// go run main.go january
// "january" has 31 days.
//
// go run main.go february
// "february" has 28 days.
//
// go run main.go march
// "march" has 31 days.
//
// go run main.go april
// "april" has 30 days.
//
// go run main.go may
// "may" has 31 days.
//
// go run main.go june
// "june" has 30 days.
//
// go run main.go july
// "july" has 31 days.
//
// go run main.go august
// "august" has 31 days.
//
// go run main.go september
// "september" has 30 days.
//
// go run main.go october
// "october" has 31 days.
//
// go run main.go november
// "november" has 30 days.
//
// go run main.go december
// "december" has 31 days.
//
// -----------------------------------------
// Your solution should be case insensitive
// -----------------------------------------
// go run main.go DECEMBER
// "DECEMBER" has 31 days.
//
// go run main.go dEcEmBeR
// "dEcEmBeR" has 31 days.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 11-if/exercises/09-days-in-month/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
"time"
)
func main() {
if len(os.Args) != 2 {
fmt.Println("Give me a month name")
return
}
// get the current year and find out whether it's a leap year
year := time.Now().Year()
leap := year%4 == 0 && (year%100 != 0 || year%400 == 0)
// setting it to 28, saves me typing it below again
days := 28
month := os.Args[1]
// case insensitive
if m := strings.ToLower(month); m == "april" ||
m == "june" ||
m == "september" ||
m == "november" {
days = 30
} else if m == "january" ||
m == "march" ||
m == "may" ||
m == "july" ||
m == "august" ||
m == "october" ||
m == "december" {
days = 31
} else if m == "february" {
// try a "logical and operator" above.
// like: `else if m == "february" && leap`
if leap {
days = 29
}
} else {
fmt.Printf("%q is not a month.\n", month)
return
}
fmt.Printf("%q has %d days.\n", month, days)
}
================================================
FILE: 11-if/exercises/README.md
================================================
# If Statement
1. **[Age Seasons](https://github.com/inancgumus/learngo/tree/master/11-if/exercises/01-age-seasons)**
2. **[Simplify It](https://github.com/inancgumus/learngo/tree/master/11-if/exercises/02-simplify-it)**
3. **[Arg Count](https://github.com/inancgumus/learngo/tree/master/11-if/exercises/03-arg-count)**
4. **[Vowel or Consonant](https://github.com/inancgumus/learngo/tree/master/11-if/exercises/04-vowel-or-cons)**
## Error Handling
5. **[Movie Ratings](https://github.com/inancgumus/learngo/tree/master/11-if/exercises/05-movie-ratings)**
6. **[Odd or Even](https://github.com/inancgumus/learngo/tree/master/11-if/exercises/06-odd-even)**
7. **[Leap Year](https://github.com/inancgumus/learngo/tree/master/11-if/exercises/07-leap-year)**
8. **[Simplify the Leap Year](https://github.com/inancgumus/learngo/tree/master/11-if/exercises/08-simplify-leap-year)**
9. **[Days in a Month](https://github.com/inancgumus/learngo/tree/master/11-if/exercises/09-days-in-month)**
================================================
FILE: 11-if/questions/1-comparison-operators.md
================================================
## Which one below is not one of the equality operators of Go?
1. `==`
2. `!=`
3. `>` *CORRECT*
> **3:** That's the greater operator. It checks whether an ordered value is greater than the other or not.
## Which one below is not one of the ordering operators of Go?
1. `>`
2. `<=`
3. `==` *CORRECT*
4. `<`
> **3:** That's the equal operator. In an expression, it checks whether a value (operand) is equal to another value (operand).
## Which one of these types is returned by the comparison operators?
1. int
2. byte
3. bool *CORRECT*
4. float64
> **3:** That's right. All the comparison operators return an untyped bool value (true or false).
## Which one of these below cannot be used as an operand to ordering operators (`>`, `<`, `>=`, `<=`)?
1. int value
2. byte value
3. string value
4. bool value *CORRECT*
5. all of them
> **1-2:** This is an ordered value, it can be used.
>
> **3:** String is an ordered value because it's a series of numbers. So, it can be used as an operand.
>
> **4:** That's right. A bool value is not an ordered value, so it cannot be used with ordering operators.
## Which one of these cannot be used as an operand to equality operators (`==`, `!=`)?
1. int value
2. byte value
3. string value
4. bool value
5. They all can be used *CORRECT*
> **5:** That's right. Every **comparable value** can be used as an operand to equality operators.
## What does this code print?
```go
fmt.Println("go" != "go!")
fmt.Println("go" == "go!")
```
1. true true
2. true false *CORRECT*
3. false true
4. false false
5. error
> **3-4:** Watch out for the exclamation mark at the end of the second string value.
## What does this code print?
```go
fmt.Println(1 == true)
```
1. true
2. 1
3. false
4. 2
5. error *CORRECT*
> **5:** That's right. A numeric constant cannot be compared to a bool value.
## What does this code print?
```go
fmt.Println(2.9 > 2.9)
fmt.Println(2.9 <= 2.9)
```
1. true true
2. true false
3. false true *CORRECT*
4. false false
5. error
## What does this code print?
```go
fmt.Println(false >= true)
fmt.Println(true <= false)
```
1. true true
2. true false
3. false true
4. false false
5. error *CORRECT*
> **5:** That's right. Bool values are not ordered values, so they cannot be compared using the comparison operators.
## How to fix this program without losing precision?
```go
package main
import "fmt"
func main() {
weight, factor := 500, 1.5
weight *= factor
fmt.Println(weight)
}
```
1. It cannot be fixed
2. `weight *= float64(factor)`
3. `weight *= int(factor)`
4. `weight = float64(weight) * factor`
5. `weight = int(float64(weight) * factor)` *CORRECT*
> **1:** It can be fixed.
>
> **2:** Type mismatch: weight is int.
>
> **3:** Lost precision: factor will be 1.
>
> **4:** Type mismatch: weight is int (cannot assign back).
>
> **5:** That's right. The result would be 750.
================================================
FILE: 11-if/questions/2-logical-operators.md
================================================
## Which one below is not one of the logical operators of Go?
1. `||`
2. `!=` *CORRECT*
3. `!`
4. `&&`
> **2:** That's the "not equal" operator. It's a comparison operator, not a logical operator.
## Which one of these types is returned by a logical operator?
1. int
2. byte
3. bool *CORRECT*
4. float64
> **3:** That's right. All the logical operators return an untyped bool value (true or false).
## Which one of these can be used as an operand to a logical operator?
1. int
2. byte
3. bool *CORRECT*
4. float64
> **3:** That's right. All the logical operators expect a bool value (or a bool expression that yields a bool value).
## Which expression below equals to the sentence below?
"age is equal or above 15 and hair color is yellow"
1. `age > 15 || hairColor == "yellow"`
2. `age < 15 || hairColor != "yellow"`
3. `age >= 15 && hairColor == "yellow"` *CORRECT*
4. `age > 15 && hairColor == "yellow"`
## What does this program print?
```go
package main
import "fmt"
func main() {
var (
on = true
off = !on
)
fmt.Println(!on && !off)
fmt.Println(!on || !off)
}
```
1. true true
2. true false
3. false true *CORRECT*
4. false false
5. error
> **3:** `!on` is false. `!off` is true. So, `!on && !off` is false. And, `!on || !off` is true.
## What does this program print?
```go
package main
import "fmt"
func main() {
on := 1
fmt.Println(on == true)
}
```
1. true
2. false
3. error *CORRECT*
> **3:** `on` is int, while `true` is a bool. So, there's a type mismatch error here. Go is not like other C based languages where `1` equals to `true`.
## What does this code print?
```go
// Note: "a" comes before "b"
a := "a" > "b"
b := "b" <= "c"
fmt.Println(a || b)
```
1. "a"
2. "b"
3. true *CORRECT*
4. false
5. error
> **1-2:** Logical operators return a bool value only.
> **3:** Order is like so: "a", "b", "c". So, `"a" > "b"` is false. `"b" <= "c"` is true. So, `a || b` is true.
> **5:** There isn't an error. Strings are actually numbers, so, they're ordered and can be compared using the ordering operators.
## What does the following program print?
```go
// Let's say that there are two functions like this:
//
// isOn() which returns true and prints "on ".
// isOff() which returns false and prints "off ".
//
// Remember: Logical operators short-circuit.
package main
import "fmt"
func main() {
_ = isOff() && isOn()
_ = isOn() || isOff()
}
// Don't mind about these functions.
// Just focus on the problem.
// They are here just for you to understand what's going on better.
func isOn() bool {
fmt.Print("on ")
return true
}
func isOff() bool {
fmt.Print("off ")
return false
}
```
1. "on off on off "
2. "off on " *CORRECT*
3. "off on on off "
4. "on off "
> **1, 3:** Remember: Logical operators short-circuit.
> **2:** That's right.
>
> In: `isOff() && isOn()`, `isOff()` returns false, so, logical AND operator short-circuits and doesn't call `isOn()`; so it prints: `"off "`.
>
> Then, in: `isOn() || isOff()`, `isOn()` returns true, so, logical OR operator short circuits and doesn't call `isOff()`; so it prints `"on "`.
> **4:** Think again.
Example program is [here](https://play.golang.org/p/6z3afaOf7yT).
================================================
FILE: 11-if/questions/3-if.md
================================================
## What does "control flow" mean?
1. Changing the top-to-bottom execution of a program
2. Changing the left-to-right execution of a program
3. Deciding which statements are executed *CORRECT*
> **1, 2:** You can't change that.
>
> **3:** That's right. Control flow allows us to decide which parts of a program is to be run depending on condition values such as true or false.
## How can you simplify the condition expression of this if statement?
```go
if (mood == "perfect") {
// this code is not important
}
```
1. `if {mood == "perfect"}`
2. `if [mood == "perfect"]`
3. `if mood = "perfect"`
4. `if mood == "perfect"` *CORRECT*
> **1, 2:** That's a syntax error. Try again.
>
> **3:** `=` is the assignment operator. It cannot be used as a condition.
>
> **4:** That's right. In Go, you don't need to use the parentheses.
## The following code doesn't work. How you can fix it?
```go
package main
import "fmt"
func main() {
// this program prints "cool"
// when the mood is "happy"
mood := "happy"
if "happy" {
fmt.Println("cool")
}
}
```
1. Just wrap the "happy" inside parentheses.
2. You need to compare mood with "happy". Like this: `if mood == "happy" { ... }` *CORRECT*
3. Just directly use `mood` instead of `happy`. Like this: `if mood { ... }`
4. This should work! This is a tricky question.
> **1:** That won't change anything. Go adds the parentheses automatically behind the scenes for every if statement.
>
> **2:** Yep. In Go, condition expressions always yield a bool value. Using a comparison operator will yield a bool value. So, it will work.
>
> **4:** No, it's not :)
## How can you simplify the following code? You only need to change the condition expression, but how?
```go
package main
import "fmt"
func main() {
happy := true
if happy == true {
fmt.Println("cool!")
}
}
```
1. `happy != false`
2. `!happy == false`
3. `happy` *CORRECT*
4. `!happy == true`
> **1, 2:** Right! But you can do it better.
>
> **3:** Perfect! You don't need to compare the value to `true`. `happy` is already true, so it'll print "cool!".
>
> **4:** That won't print anything. `!happy` yields false.
## How can you simplify the following code? You only need to change the condition expression, but how?
```go
package main
import "fmt"
func main() {
happy := false
if happy == !true {
fmt.Println("why not?")
}
}
```
1. Easy! Like this: `happy != true`
2. `!happy` *CORRECT*
3. `happy == false`
4. `!happy == false`
> **1, 3:** Right! But you can do it better.
>
> **2:** Perfect! You don't need to compare the value to `false` or to `!true` (which is false). `!happy` already returns true, because it's false at the beginning.
>
> **4:** That won't print anything. `happy` will be true.
## This code contains an error. How to fix it?
```go
package main
import "fmt"
func main() {
happy := false
if happy {
fmt.Println("cool!")
} else if !happy {
fmt.Println("why not?")
} else {
fmt.Println("why not?")
} else {
fmt.Println("why not?")
}
}
```
1. Remove one of the else branches. *CORRECT*
2. Move the else if as the last branch.
3. It repeats "why not?" several times.
4. Remove the `else if` branch.
> **1:** Right. There can be only one else branch.
>
> **2:** If there's an else branch, you can't move else if branch as the last branch.
>
> **3, 4:** So? :) That's not the cause of the problem.
>
## What's the problem with the following code?
```go
package main
import "fmt"
func main() {
happy := true
energic := happy
if happy {
fmt.Println("cool!")
} else if !happy {
fmt.Println("why not?")
} else if energic {
fmt.Println("working out?")
}
}
```
1. It declares the energic variable unnecessarily.
2. You can't use more than one else if branch.
3. It will never run the last else if branch. *CORRECT*
4. There's no else branch.
> **2:** Well, actually you can.
>
> **3:** Right. `happy` can only be either true or false. That means, it will always execute the first two branches, but it will never execute the else if branch.
>
> **4:** It doesn't have to be. Else branch is optional.
## How can you simplify the following code?
```go
package main
import "fmt"
func main() {
happy := false
if happy {
fmt.Println("cool!")
} else if happy != true {
fmt.Println("why not?")
} else {
fmt.Println("why not?")
}
}
```
1. Change `else if`'s condition to: `!happy`.
2. Move the else branch before else if.
3. Remove the else branch.
4. Remove the else if branch. *CORRECT*
> **1, 3:** Close! But, you can do it even better.
>
> **2:** You can't: `else` branch should be the last branch.
>
> **4:** Cool. That's not necessary because `else` branch already handless "unhappy" situation. It's simpler because it doesn't have a condition.
================================================
FILE: 11-if/questions/4-error-handling.md
================================================
## Why error handling is needed?
1. I don't know.
2. To control the execution flow.
3. To make a program malware safe.
4. Because, things can go wrong. *CORRECT*
> **1:** Then, please watch the lecture again! :)
>
> **2:** Actually yes, but that's not the main reason.
>
> **3:** Come on!
## What's a nil value?
1. The dark matter that rules the universe.
2. It's a zero value for pointers or pointer-based types. It means the value is uninitialized. *CORRECT*
3. It's equal to empty string: `"" == nil` is true.
## What's an error value?
1. It stores the error details *CORRECT*
2. A global variable which stores the error status.
3. A global constant which stores the error status.
> **2, 3:** There aren't any global variables in Go. There are only package level variables. And, since the error value is just a value, so it can be stored in any variable.
>
## How Go handles error handling?
1. Using a throw/catch statement
2. Using a simple if statement with nil comparison *CORRECT*
3. Using a mechanism called tagging
> **1:** There isn't a throw/catch statement in Go; unlike Java, C#, and so on... Go is explicit.
## When you should handle the errors?
1. After the main func ends.
2. Before calling a function.
3. Immediately, after calling a function which returns an error value. *CORRECT*
## For which one of the following functions that you might want to handle the errors?
```go
func Read() error
func Write() error
func String() string
func Reset()
```
1. Read and Write *CORRECT*
2. String and Reset
3. Read, Write and Reset
4. For neither of them
5. For all of them
> **1:** They return error values. So, you might want to handle the errors after you call them.
>
> **2:** They don't return error values. So, you don't have to handle any errors.
>
> **3:** Partially true. Try again.
## Let's say a function returns a nil error value. So, what does that mean?
1. The function call failed.
2. The function call is successful. *CORRECT*
3. The function call is in an indeterministic state. We can't know.
## Let's say a function returns a non-nil error value. So, what does that mean?
1. The function call failed. *CORRECT*
2. The function call is successful.
3. The function call is in an indeterministic state. We can't know.
> **1:** Yep. Later on you'll learn that, this is not always true. Sometimes a function can return a non-nil error value, and the returned value may indicate something rather than an error. Search on Google: golang io EOF error if you're curious.
## Does the following program correctly handles the error?
**NOTE:** This is what the `ParseDuration` function looks like:
```go
func ParseDuration(s string) (Duration, error)
```
```go
package main
import (
"fmt"
"time"
)
func main() {
d, err := time.ParseDuration("1h10s")
if err != nil {
fmt.Println(d)
}
}
```
1. Yes. It prints the parsed duration if it's successful.
2. No. It doesn't check for the errors.
3. No. It prints the duration even when there's an error. *CORRECT*
> **1:** Yes, it handles the error; however it does so incorrectly. Something is missing here. Look closely.
>
> **2:** Actually, it does.
>
> **3:** That's right. It shouldn't use the returned value when there's an error.
## Does the following program correctly handles the error?
**NOTE:** This is what the `ParseDuration` function looks like:
```go
func ParseDuration(s string) (Duration, error)
```
```go
package main
import (
"fmt"
"time"
)
func main() {
d, err := time.ParseDuration("1h10s")
if err != nil {
fmt.Println("Parsing error:", err)
return
}
fmt.Println(d)
}
```
1. Yes. It prints the parsed duration if it's successful. *CORRECT*
2. No. It doesn't check for the errors.
3. No. It prints the duration even when there's an error.
> **1:** That's right. When there's an error, it prints a message and it quits from the program.
>
> **2:** Actually, it does.
>
> **3:** No, it does not. It only prints it when there isn't an error.
================================================
FILE: 11-if/questions/5-short-if.md
================================================
## How to fix this program?
```go
package main
import (
"fmt"
"time"
)
func main() {
if err != nil; d, err := time.ParseDuration("1h10s") {
fmt.Println(d)
}
}
```
1. Swap the simple statement with the `err != nil` check. *CORRECT*
2. Remove the error handling.
3. Remove the semicolon.
4. Change the short declaration to an assignment.
> **1:** Yes. In a short if statement, the simple statement (the short declaration there) should be the first part of it. Then, after the semicolon separator, there should be a condition expression.
>
> **2:** You don't want that. That's not the issue here.
## What does this program print?
```go
package main
import "fmt"
func main() {
done := false
if done := true; done {
fmt.Println(done)
}
fmt.Println(done)
}
```
1. true and true
2. false and false
3. true and false *CORRECT*
4. false and true
> **3:** Yes. It shadows the main()'s done variable, and inside the if statement, it prints "true". Then, after the if statement ends, it prints the main()'s done variable which is "false".
## There's a shadowing issue in this program. The program should print: 10, now it prints: 0.
**How can you fix this it?**
```go
package main
import (
"fmt"
"strconv"
)
func main() {
var n int
if n, err := strconv.Atoi("10"); err != nil {
fmt.Printf("error: %s (n: %d)", err, n)
return
}
fmt.Println(n)
}
```
_See the code also in here: https://play.golang.org/p/fDrmcXWGnQB_
1. Remove the first declaration (main()'s n variable).
2. Remove the declaration in the short-if (if's n).
3. Declare an error variable outside of the main.
4. Declare an error variable along with main's n variable, then change the short-if declaration to an assignment. *CORRECT*
> **1:** That will break the program. Because, the last line prints it.
>
> **2:** The program uses it to set the n.
>
> **3:** There will be "unused variable" error.
> **4:** Yes, that will solve the shadowing issue. Short-if will reuse the same 'n' variable (main()'s n). So, the converted number 'n' will be printed as: 10. See the solution here: https://play.golang.org/p/6jc-nZJNHYb
================================================
FILE: 12-switch/01-one-case/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
city := "Paris"
switch city {
case "Paris":
fmt.Println("France")
}
// SIMILAR TO IF
// ------------------------------------
// switch statement is converted to an if statement
// automatically behind the scenes
//
// above switch statement is similar to this if
// if city == "Paris" {
// fmt.Println("France")
// }
}
================================================
FILE: 12-switch/02-multiple-cases/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
city := os.Args[1]
switch city {
case "Paris":
fmt.Println("France")
// break // unnecessary in Go
// vip := true
// fmt.Println("VIP trip?", vip)
case "Tokyo":
fmt.Println("Japan")
// fmt.Println("VIP trip?", vip)
}
// if city == "Paris" {
// fmt.Println("France")
// } else if city == "Tokyo" {
// fmt.Println("Japan")
// }
}
================================================
FILE: 12-switch/03-default-clause/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
city := os.Args[1]
switch city {
case "Paris":
fmt.Println("France")
case "Tokyo":
fmt.Println("Japan")
default:
fmt.Println("Where?")
// there can be only one default in a switch
// default:
// fmt.Println("Where?")
}
// if city == "Paris" {
// fmt.Println("France")
// } else if city == "Tokyo" {
// fmt.Println("Japan")
// } else {
// fmt.Println("Where?")
// }
}
================================================
FILE: 12-switch/04-multiple-conditions/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
city := os.Args[1]
switch city {
case "Paris", "Lyon":
fmt.Println("France")
case "Tokyo":
fmt.Println("Japan")
}
// if city == "Paris" || city == "Lyon" {
// fmt.Println("France")
// } else if city == "Tokyo" {
// fmt.Println("Japan")
// }
}
================================================
FILE: 12-switch/05-bool-expressions/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
i := 10
switch {
case i > 0:
fmt.Println("positive")
case i < 0:
fmt.Println("negative")
default:
fmt.Println("zero")
}
}
================================================
FILE: 12-switch/06-fallthrough/01-without/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
i := 142
switch {
case i > 100:
fmt.Print("big positive number")
case i > 0:
fmt.Print("positive number")
default:
fmt.Print("number")
}
fmt.Println()
}
================================================
FILE: 12-switch/06-fallthrough/02-with/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
i := 142
switch {
case i > 100:
fmt.Print("big ")
fallthrough
case i > 0:
fmt.Print("positive ")
fallthrough
default:
fmt.Print("number")
}
fmt.Println()
}
================================================
FILE: 12-switch/07-short-switch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// i := 10
// true is in a comment now
// you can delete that part if you want
// it's by default true anyway.
switch i := 10; /* true */ {
case i > 0:
fmt.Println("positive")
case i < 0:
fmt.Println("negative")
default:
fmt.Println("zero")
}
}
================================================
FILE: 12-switch/08-parts-of-the-day/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
// time.Now() gets the current time
// and in turn, .Hour() gets the current hour from it
// h := time.Now().Hour()
// fmt.Println("Current hour is", h)
switch h := time.Now().Hour(); {
case h >= 18: // 18 to 23
fmt.Println("good evening")
case h >= 12: // 12 to 18
fmt.Println("good afternoon")
case h >= 6: // 6 to 12
fmt.Println("good morning")
default: // 0 to 5
fmt.Println("good night")
}
// h is not available here
// it's bound to switch statement's block
// fmt.Println(h)
}
================================================
FILE: 12-switch/09-when-to-use/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
if len(os.Args) != 2 {
fmt.Println("Gimme a month name.")
return
}
// m := os.Args[1]
// if m == "Dec" || m == "Jan" || m == "Feb" {
// fmt.Println("Winter")
// } else if m == "Mar" || m == "Apr" || m == "May" {
// fmt.Println("Spring")
// } else if m == "Jun" || m == "Jul" || m == "Aug" {
// fmt.Println("Summer")
// } else if m == "Sep" || m == "Oct" || m == "Nov" {
// fmt.Println("Fall")
// } else {
// fmt.Println("ERROR: not a month.")
// }
switch m := os.Args[1]; m {
case "Dec", "Jan", "Feb":
fmt.Println("Winter")
case "Mar", "Apr", "May":
fmt.Println("Spring")
case "Jun", "Jul", "Aug":
fmt.Println("Summer")
case "Sep", "Oct", "Nov":
fmt.Println("Fall")
default:
fmt.Printf("%q is not a month.\n", m)
}
}
================================================
FILE: 12-switch/exercises/01-richter-scale/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// STORY
// You're curious about the richter scales. When reporters
// say: "There's been a 5.5 magnitude earthquake",
//
// You want to know what that means.
//
// So, you've decided to write a program to do that for you.
//
// EXERCISE: Richter Scale
//
// 1. Get the earthquake magnitude from the command-line.
// 2. Display its corresponding description.
//
// ---------------------------------------------------------
// MAGNITUDE DESCRIPTION
// ---------------------------------------------------------
// Less than 2.0 micro
// 2.0 and less than 3.0 very minor
// 3.0 and less than 4.0 minor
// 4.0 and less than 5.0 light
// 5.0 and less than 6.0 moderate
// 6.0 and less than 7.0 strong
// 7.0 and less than 8.0 major
// 8.0 and less than 10.0 great
// 10.0 or more massive
//
// EXPECTED OUTPUT
// go run main.go
// Give me the magnitude of the earthquake.
//
// go run main.go ABC
// I couldn't get that, sorry.
//
// go run main.go 0.5
// 0.50 is micro
//
// go run main.go 2.5
// 2.50 is very minor
//
// go run main.go 3
// 3.00 is minor
//
// go run main.go 4.5
// 4.50 is light
//
// go run main.go 5
// 5.00 is moderate
//
// go run main.go 6
// 6.00 is strong
//
// go run main.go 7
// 7.00 is major
//
// go run main.go 8
// 8.00 is great
//
// go run main.go 11
// 11.00 is massive
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 12-switch/exercises/01-richter-scale/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
args := os.Args
if len(args) != 2 {
fmt.Println("Give me the magnitude of the earthquake.")
return
}
richter, err := strconv.ParseFloat(args[1], 64)
if err != nil {
fmt.Println("I couldn't get that, sorry.")
return
}
var desc string
switch r := richter; {
case r < 2:
desc = "micro"
case r >= 2 && r < 3:
desc = "very minor"
case r >= 3 && r < 4:
desc = "minor"
case r >= 4 && r < 5:
desc = "light"
case r >= 5 && r < 6:
desc = "moderate"
case r >= 6 && r < 7:
desc = "strong"
case r >= 7 && r < 8:
desc = "major"
case r >= 8 && r < 10:
desc = "great"
default:
desc = "massive"
}
fmt.Printf("%.2f is %s\n", richter, desc)
}
================================================
FILE: 12-switch/exercises/02-richter-scale-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Richter Scale #2
//
// Repeat the previous exercise.
//
// But, this time, get the description and print the
// corresponding richter scale.
//
// See the expected outputs.
//
// ---------------------------------------------------------
// MAGNITUDE DESCRIPTION
// ---------------------------------------------------------
// Less than 2.0 micro
// 2.0 to less than 3.0 very minor
// 3.0 to less than 4.0 minor
// 4.0 to less than 5.0 light
// 5.0 to less than 6.0 moderate
// 6.0 to less than 7.0 strong
// 7.0 to less than 8.0 major
// 8.0 to less than 10.0 great
// 10.0 or more massive
//
// EXPECTED OUTPUT
// go run main.go
// Tell me the magnitude of the earthquake in human terms.
//
// go run main.go alien
// alien's richter scale is unknown
//
// go run main.go micro
// micro's richter scale is less than 2.0
//
// go run main.go "very minor"
// very minor's richter scale is 2 - 2.9
//
// go run main.go minor
// minor's richter scale is 3 - 3.9
//
// go run main.go light
// light's richter scale is 4 - 4.9
//
// go run main.go moderate
// moderate's richter scale is 5 - 5.9
//
// go run main.go strong
// strong's richter scale is 6 - 6.9
//
// go run main.go major
// major's richter scale is 7 - 7.9
//
// go run main.go great
// great's richter scale is 8 - 9.9
//
// go run main.go massive
// massive's richter scale is 10+
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 12-switch/exercises/02-richter-scale-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
args := os.Args
if len(args) != 2 {
fmt.Println("Tell me the magnitude of the earthquake in human terms.")
return
}
var richter string
desc := args[1]
switch desc {
case "micro":
richter = "less than 2.0"
case "very minor":
richter = "2 - 2.9"
case "minor":
richter = "3 - 3.9"
case "light":
richter = "4 - 4.9"
case "moderate":
richter = "5 - 5.9"
case "strong":
richter = "6 - 6.9"
case "major":
richter = "7 - 7.9"
case "great":
richter = "8 - 9.9"
case "massive":
richter = "10+"
default:
richter = "unknown"
}
fmt.Printf(
"%s's richter scale is %s\n",
desc, richter,
)
}
================================================
FILE: 12-switch/exercises/03-convert/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// ---------------------------------------------------------
// EXERCISE: Convert
//
// Convert the if statement to a switch statement.
// ---------------------------------------------------------
const (
usage = "Usage: [username] [password]"
errUser = "Access denied for %q.\n"
errPwd = "Invalid password for %q.\n"
accessOK = "Access granted to %q.\n"
user, user2 = "jack", "inanc"
pass, pass2 = "1888", "1879"
)
func main() {
args := os.Args
if len(args) != 3 {
fmt.Println(usage)
return
}
u, p := args[1], args[2]
//
// REFACTOR THIS TO A SWITCH
//
if u != user && u != user2 {
fmt.Printf(errUser, u)
} else if u == user && p == pass {
fmt.Printf(accessOK, u)
} else if u == user2 && p == pass2 {
fmt.Printf(accessOK, u)
} else {
fmt.Printf(errPwd, u)
}
}
================================================
FILE: 12-switch/exercises/03-convert/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
const (
usage = "Usage: [username] [password]"
errUser = "Access denied for %q.\n"
errPwd = "Invalid password for %q.\n"
accessOK = "Access granted to %q.\n"
user, user2 = "jack", "inanc"
pass, pass2 = "1888", "1879"
)
func main() {
args := os.Args
if len(args) != 3 {
fmt.Println(usage)
return
}
u, p := args[1], args[2]
// More readable, right? 👍
switch {
case u != user && u != user2:
fmt.Printf(errUser, u)
case u == user && p == pass:
// notice this one (no more duplication)
fallthrough
case u == user2 && p == pass2:
fmt.Printf(accessOK, u)
default:
fmt.Printf(errPwd, u)
}
}
================================================
FILE: 12-switch/exercises/04-string-manipulator/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// STORY
// You want to write a program that will manipulate a
// given string to uppercase, lowercase, and title case.
//
// EXERCISE: String Manipulator
//
// 1. Get the operation as the first argument.
//
// 2. Get the string to be manipulated as the 2nd argument.
//
// HINT
// You can find the manipulation functions in the strings
// package Go documentation (ToLower, ToUpper, Title).
//
// EXPECTED OUTPUT
//
// go run main.go
// [command] [string]
//
// Available commands: lower, upper and title
//
// go run main.go lower 'OMG!'
// omg!
//
// go run main.go upper 'omg!'
// OMG!
//
// go run main.go title "mr. charles darwin"
// Mr. Charles Darwin
//
// go run main.go genius "mr. charles darwin"
// Unknown command: "genius"
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 12-switch/exercises/04-string-manipulator/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
const usage = `[command] [string]
Available commands: lower, upper and title`
func main() {
args := os.Args
if len(args) != 3 {
fmt.Println(usage)
return
}
cmd, str := args[1], args[2]
switch cmd {
case "lower":
fmt.Println(strings.ToLower(str))
case "upper":
fmt.Println(strings.ToUpper(str))
case "title":
fmt.Println(strings.Title(str))
default:
fmt.Printf("Unknown command: %q\n", cmd)
}
}
================================================
FILE: 12-switch/exercises/05-days-in-month/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
"time"
)
// ---------------------------------------------------------
// EXERCISE: Days in a Month
//
// Refactor the previous exercise from the if statement
// section.
//
// "Print the number of days in a given month."
//
// Use a switch statement instead of if statements.
// ---------------------------------------------------------
func main() {
if len(os.Args) != 2 {
fmt.Println("Give me a month name")
return
}
year := time.Now().Year()
leap := year%4 == 0 && (year%100 != 0 || year%400 == 0)
days, month := 28, os.Args[1]
if m := strings.ToLower(month); m == "april" ||
m == "june" ||
m == "september" ||
m == "november" {
days = 30
} else if m == "january" ||
m == "march" ||
m == "may" ||
m == "july" ||
m == "august" ||
m == "october" ||
m == "december" {
days = 31
} else if m == "february" {
if leap {
days = 29
}
} else {
fmt.Printf("%q is not a month.\n", month)
return
}
fmt.Printf("%q has %d days.\n", month, days)
}
================================================
FILE: 12-switch/exercises/05-days-in-month/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
"time"
)
func main() {
if len(os.Args) != 2 {
fmt.Println("Give me a month name")
return
}
year := time.Now().Year()
leap := year%4 == 0 && (year%100 != 0 || year%400 == 0)
days, month := 28, os.Args[1]
switch strings.ToLower(month) {
case "april", "june", "september", "november":
days = 30
case "january", "march", "may", "july",
"august", "october", "december":
days = 31
case "february":
if leap {
days = 29
}
default:
fmt.Printf("%q is not a month.\n", month)
return
}
fmt.Printf("%q has %d days.\n", month, days)
}
================================================
FILE: 12-switch/exercises/README.md
================================================
# Switch Statement
1. **[Richter Scale](https://github.com/inancgumus/learngo/tree/master/12-switch/exercises/01-richter-scale)**
2. **[Richter Scale #2](https://github.com/inancgumus/learngo/tree/master/12-switch/exercises/02-richter-scale-2)**
3. **[Convert](https://github.com/inancgumus/learngo/tree/master/12-switch/exercises/03-convert)**
4. **[String Manipulator](https://github.com/inancgumus/learngo/tree/master/12-switch/exercises/04-string-manipulator)**
5. **[Days in a Month](https://github.com/inancgumus/learngo/tree/master/12-switch/exercises/05-days-in-month)**
================================================
FILE: 12-switch/questions/questions.md
================================================
## What's the difference between if and switch statements?
1. If statements control the execution flow but switch statements do not
2. If statements are much more readable alternatives to switch statements
3. Switch statements are much more readable alternatives to if statements *CORRECT*
> **1:** They both control the execution flow.
>
> **2:** Sometimes true, but, for complex if statements, switch statement can make them much more readable.
## What type of values can you use as a switch condition?
```go
switch condition {
// ....
}
```
1. int
2. bool
3. string
4. Any type of values *CORRECT*
> **4:** Unlike most other C based languages, in Go, a switch statement is actually a syntactic-sugar for a if statement. This means that, Go converts a switch statement into an if statement behind the scenes. So, any type of values can be used as a condition.
## What type of values can you use as the case conditions for the following switch statement?
```go
switch false {
case condition:
// ...
}
```
1. int
2. bool *CORRECT*
3. string
4. Any type of values
> **2:** Yes, you can only use bool values because in the example, the switch's condition is a bool.
## What type of values can you use as the case conditions for the following switch statement?
```go
switch "go" {
case condition:
// ...
}
```
1. int
2. bool
3. string *CORRECT*
4. Any type of values
> **3:** Yes, you can only use string values because in the example, the switch's condition is a string.
## What's the problem in the following code?
```go
switch 5 {
case 5:
case 6:
case 5:
}
```
1. Case clauses don't have any statements
2. The same constants are used multiple times in case conditions *CORRECT*
3. Switch condition cannot be an untyped int
> **2:** That's right. 5 is used by multiple case clauses as case conditions. It should be used only once.
## When the following code runs, which case will be executed?
```go
weather := "hot"
switch weather {
case "very cold", "cold":
// ...
case "very hot", "hot":
// ...
default:
// ...
}
```
1. None of them
2. The first case clause
3. The second case clause *CORRECT*
4. The default clause
> **3:** That's right. When switch's condition is either "hot" or "very hot", the 2nd case will be executed.
## When the following code runs, which clause will be executed?
```go
switch weather := "too hot"; weather {
default:
// ...
case "very cold", "cold":
// ...
case "very hot", "hot":
// ...
}
```
1. None of them
2. The first case clause
3. The second case clause
4. The default clause *CORRECT*
> **4:** That's right. The switch's condition doesn't match to any of the case conditions, so the default clause will be executed as a last resort. And the default clause can be in any place inside a switch statement.
## When the following code runs, which case will be executed?
```go
switch weather := "too hot"; weather {
case "very cold", "cold":
// ...
case "very hot", "hot":
// ...
}
```
1. None of them *CORRECT*
2. The first case clause
3. The second case clause
4. The default clause
> **1:** That's right. The switch's condition doesn't match to any of the case conditions, and there isn't a default clause. So, none of the clauses will be executed.
## What does the following program print?
```go
richter := 2.5
switch r := richter; {
case r < 2:
fallthrough
case r >= 2 && r < 3:
fallthrough
case r >= 5 && r < 6:
fmt.Println("Not important")
case r >= 6 && r < 7:
fallthrough
case r >= 7:
fmt.Println("Destructive")
}
```
1. Nothing
2. "Not important" *CORRECT*
3. "Destructive"
> **2:** That's right! When fallthrough is used, the following clause will be executed without checking its condition.
## What's the problem in the following code?
```go
richter := 14.5
switch r := richter; {
case r >= 5 && r < 6:
fallthrough
fmt.Println("Moderate")
default:
fmt.Println("Unknown")
case r >= 7:
fmt.Println("Destructive")
}
```
1. default clause should be the last clause
2. default clause should have a fallthrough statement
3. The first case should use the fallthrough statement as its last statement *CORRECT*
> **3:** That's right! In a case block, fallthrough can only be used as the last statement.
## What does the following program print?
```go
n := 8
switch {
case n > 5, n < 1:
fmt.Println("n is big")
case n == 8:
fmt.Println("n is 8")
}
```
1. Nothing
2. "n is 8"
3. "n is big" *CORRECT*
> **3:** That's right! Switch runs top-to-bottom and case conditions run left-to-right. Here, 1st case's 1st condition expression (which is n > 5) will yield true, so the 1st case will be executed.
================================================
FILE: 13-loops/01-basics/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var sum int
// sum += 1
// sum += 2
// sum += 3
// sum += 4
// sum += 5
for i := 1; i <= 1000; i++ {
sum += i
}
fmt.Println(sum)
}
================================================
FILE: 13-loops/02-break/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var (
sum int
i = 1
)
for {
if i > 5 {
break
}
sum += i
fmt.Println(i, "-->", sum)
i++
}
fmt.Println(sum)
}
================================================
FILE: 13-loops/03-continue/01-a-before/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var (
sum int
i = 1
)
for {
if i > 10 {
break
}
if i%2 != 0 {
// this continue creates an endless loop
// since the code never increases the i
continue
}
sum += i
fmt.Println(i, "-->", sum)
i++
}
fmt.Println(sum)
}
================================================
FILE: 13-loops/03-continue/01-b-after/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var (
sum int
i = 1
)
for {
if i > 10 {
break
}
if i%2 != 0 {
// just by putting this here we solve the problem
i++
continue
}
sum += i
fmt.Println(i, "-->", sum)
i++
}
fmt.Println(sum)
}
================================================
FILE: 13-loops/04-nested-loops-multiplication-table/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// EXERCISE: Get the `max` from the user
// And create the table according to that.
const max = 5
func main() {
// print the header
fmt.Printf("%5s", "X")
for i := 0; i <= max; i++ {
fmt.Printf("%5d", i)
}
fmt.Println()
for i := 0; i <= max; i++ {
// print the vertical header
fmt.Printf("%5d", i)
// print the cells
for j := 0; j <= max; j++ {
fmt.Printf("%5d", i*j)
}
fmt.Println()
}
}
================================================
FILE: 13-loops/05-for-range/01-loop-over-slices/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
// i := 1
// fmt.Printf("%q\n", os.Args[1])
// fmt.Printf("%q\n", os.Args[i])
// i++
// fmt.Printf("%q\n", os.Args[2])
// fmt.Printf("%q\n", os.Args[i])
// i++
// fmt.Printf("%q\n", os.Args[3])
// fmt.Printf("%q\n", os.Args[i])
// --------------------------------
// #1st way:
// --------------------------------
// for i := 1; i < len(os.Args); i++ {
// fmt.Printf("%q\n", os.Args[i])
// }
// --------------------------------
// #2nd way:
// --------------------------------
// for i, v := range os.Args {
// if i == 0 {
// continue
// }
// fmt.Printf("%q\n", v)
// }
// --------------------------------
// #3rd way (best):
// --------------------------------
for _, v := range os.Args[1:] {
fmt.Printf("%q\n", v)
}
}
================================================
FILE: 13-loops/05-for-range/02-loop-over-words/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
// this will split the following string by spaces
// and then it will put it inside words variable
// as a slice of strings
words := strings.Fields(
"lazy cat jumps again and again and again",
)
// 1 2 3 4 5 6 7 8
// --------------------------------
// #1st way:
// --------------------------------
// for j := 0; j < len(words); j++ {
// fmt.Printf("#%-2d: %q\n", j+1, words[j])
// }
// --------------------------------
// #2nd way (best):
// --------------------------------
for i, v := range words {
fmt.Printf("#%-2d: %q\n", i+1, v)
}
// --------------------------------
// #3rd way (reuse mechanism):
// --------------------------------
// var (
// i int
// v string
// )
// for i, v = range words {
// fmt.Printf("#%-2d: %q\n", i+1, v)
// }
// fmt.Printf("Last value of i and v %d %q\n", i, v)
}
================================================
FILE: 13-loops/06-project-lucky-number-game/01-randomization/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// rand.Seed(10)
// rand.Seed(100)
// t := time.Now()
// rand.Seed(t.UnixNano())
// ^-- same:
rand.Seed(time.Now().UnixNano())
guess := 10
for n := 0; n != guess; {
n = rand.Intn(guess + 1)
fmt.Printf("%d ", n)
}
fmt.Println()
}
================================================
FILE: 13-loops/06-project-lucky-number-game/02-game/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
const (
maxTurns = 5 // less is more difficult
usage = `Welcome to the Lucky Number Game! 🍀
The program will pick %d random numbers.
Your mission is to guess one of those numbers.
The greater your number is, harder it gets.
Wanna play?
`
)
func main() {
rand.Seed(time.Now().UnixNano())
args := os.Args[1:]
if len(args) != 1 {
// fmt.Println("Pick a number.")
fmt.Printf(usage, maxTurns)
return
}
guess, err := strconv.Atoi(args[0])
if err != nil {
fmt.Println("Not a number.")
return
}
if guess < 0 {
fmt.Println("Please pick a positive number.")
return
}
for turn := 0; turn < maxTurns; turn++ {
n := rand.Intn(guess + 1)
if n == guess {
fmt.Println("🎉 YOU WIN!")
return
}
}
fmt.Println("☠️ YOU LOST... Try again?")
}
================================================
FILE: 13-loops/07-project-word-finder/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
const corpus = "lazy cat jumps again and again and again"
func main() {
words := strings.Fields(corpus)
query := os.Args[1:]
// after the inner loop breaks
// this parent loop will look for the next queried word
for _, q := range query {
// "break" will terminate this loop
for i, w := range words {
if q == w {
fmt.Printf("#%-2d: %q\n", i+1, w)
// find the first word then break
// the nested loop
break
}
}
}
}
================================================
FILE: 13-loops/08-word-finder-labeled-break/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
const corpus = "lazy cat jumps again and again and again"
func main() {
words := strings.Fields(corpus)
query := os.Args[1:]
// labels and other names do not share the same scope
// var queries string
// _ = queries
// this label labels the parent loop below
// label's scope is the whole function body
// not only it's block
queries:
for _, q := range query {
for i, w := range words {
if q == w {
fmt.Printf("#%-2d: %q\n", i+1, w)
// find the first word then quit
break queries
}
}
}
}
================================================
FILE: 13-loops/09-word-finder-labeled-continue/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
const corpus = "lazy cat jumps again and again and again"
func main() {
words := strings.Fields(corpus)
query := os.Args[1:]
queries:
for _, q := range query {
for i, w := range words {
if q == w {
fmt.Printf("#%-2d: %q\n", i+1, w)
// skip duplicate words
continue queries
}
}
}
}
================================================
FILE: 13-loops/10-word-finder-labeled-switch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
const corpus = "lazy cat jumps again and again and again"
func main() {
words := strings.Fields(corpus)
query := os.Args[1:]
// labels and other names do not share the same scope
// this will work even though `queries` label exists
//
// var queries string
// _ = queries
// this label labels the parent loop below.
// label's scope is the whole func main()
queries:
for _, q := range query {
search:
for i, w := range words {
switch q {
case "and", "or", "the":
break search
}
if q == w {
fmt.Printf("#%-2d: %q\n", i+1, w)
// find the first word then quit
continue queries
}
}
}
}
================================================
FILE: 13-loops/11-goto/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
// cannot step over any variable declarations
// ERROR: "i" variable is declared after the jump
//
// goto loop
var i int
loop:
if i < 3 {
fmt.Println("looping")
i++
goto loop
}
fmt.Println("done")
}
================================================
FILE: 13-loops/exercises/01-basics.md
================================================
# Loops
1. **[Sum the Numbers](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/01-sum-the-numbers)**
2. **[Sum the Numbers: Verbose Edition](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/02-sum-the-numbers-verbose)**
3. **[Sum up to N](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/03-sum-up-to-n)**
4. **[Only Evens](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/04-only-evens)**
5. **[Break Up](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/05-break-up)**
6. **[Infinite Kill](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/06-infinite-kill)**
================================================
FILE: 13-loops/exercises/01-sum-the-numbers/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Sum the Numbers
//
// 1. By using a loop, sum the numbers between 1 and 10.
// 2. Print the sum.
//
// EXPECTED OUTPUT
// Sum: 55
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/01-sum-the-numbers/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var sum int
for i := 1; i <= 10; i++ {
sum += i
}
fmt.Println("Sum:", sum)
}
================================================
FILE: 13-loops/exercises/02-multiplication-table.md
================================================
# Multiplication Table
1. **[Dynamic Table](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/07-multiplication-table-exercises/01-dynamic-table)**
2. **[Math Table](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/07-multiplication-table-exercises/02-math-tables)**
================================================
FILE: 13-loops/exercises/02-sum-the-numbers-verbose/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Sum the Numbers: Verbose Edition
//
// By using a loop, sum the numbers between 1 and 10.
//
// HINT
// 1. For printing it as in the expected output, use Print
// and Printf functions. They don't print a newline
// automatically (unlike a Println).
//
// 2. Also, you need to use an if statement to prevent
// printing the last plus sign.
//
// EXPECTED OUTPUT
// 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = 55
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/02-sum-the-numbers-verbose/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
const min, max = 1, 10
var sum int
for i := min; i <= max; i++ {
sum += i
fmt.Print(i)
if i < max {
fmt.Print(" + ")
}
}
fmt.Printf(" = %d\n", sum)
}
================================================
FILE: 13-loops/exercises/03-lucky-number.md
================================================
# Lucky Number
1. **[First Turn Winner](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/08-lucky-number-exercises/01-first-turn-winner)**
2. **[Random Messages](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/08-lucky-number-exercises/02-random-messages)**
3. **[Double Guesses](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/08-lucky-number-exercises/03-double-guesses)**
4. **[Verbose Mode](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/08-lucky-number-exercises/04-verbose-mode)**
5. **[Enough Picks](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/08-lucky-number-exercises/05-enough-picks)**
6. **[Dynamic Difficulty](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/08-lucky-number-exercises/06-dynamic-difficulty)**
================================================
FILE: 13-loops/exercises/03-sum-up-to-n/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Sum up to N
//
// 1. Get two numbers from the command-line: min and max
// 2. Convert them to integers (using Atoi)
// 3. By using a loop, sum the numbers between min and max
//
// RESTRICTIONS
// 1. Be sure to handle the errors. So, if a user doesn't
// pass enough arguments or she passes non-numerics,
// then warn the user and exit from the program.
//
// 2. Also, check that, min < max.
//
// HINT
// For converting the numbers, you can use `strconv.Atoi`.
//
// EXPECTED OUTPUT
// Let's suppose that the user runs it like this:
//
// go run main.go 1 10
//
// Then it should print:
//
// 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = 55
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/03-sum-up-to-n/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) != 3 {
fmt.Println("gimme two numbers")
return
}
min, err1 := strconv.Atoi(os.Args[1])
max, err2 := strconv.Atoi(os.Args[2])
if err1 != nil || err2 != nil || min >= max {
fmt.Println("wrong numbers")
return
}
var sum int
for i := min; i <= max; i++ {
sum += i
fmt.Print(i)
if i < max {
fmt.Print(" + ")
}
}
fmt.Printf(" = %d\n", sum)
}
================================================
FILE: 13-loops/exercises/04-only-evens/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Only Evens
//
// 1. Extend the "Sum up to N" exercise
// 2. Sum only the even numbers
//
// RESTRICTIONS
// Skip odd numbers using the `continue` statement
//
// EXPECTED OUTPUT
// Let's suppose that the user runs it like this:
//
// go run main.go 1 10
//
// Then it should print:
//
// 2 + 4 + 6 + 8 + 10 = 30
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/04-only-evens/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) < 3 {
fmt.Println("gimme two numbers")
return
}
min, err1 := strconv.Atoi(os.Args[1])
max, err2 := strconv.Atoi(os.Args[2])
if err1 != nil || err2 != nil || min >= max {
fmt.Println("wrong numbers")
return
}
var sum int
for i := min; i <= max; i++ {
if i%2 != 0 {
continue
}
sum += i
fmt.Print(i)
if i < max-1 {
fmt.Print(" + ")
}
}
fmt.Printf(" = %d\n", sum)
}
================================================
FILE: 13-loops/exercises/04-word-finder.md
================================================
# Word Finder
1. **[Case Insensitive Search](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/09-word-finder-exercises/01-case-insensitive)**
2. **[Path Searcher](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/09-word-finder-exercises/02-path-searcher)**
================================================
FILE: 13-loops/exercises/05-break-up/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Break Up
//
// 1. Extend the "Only Evens" exercise
// 2. This time, use an infinite loop.
// 3. Break the loop when it reaches to the `max`.
//
// RESTRICTIONS
// You should use the `break` statement once.
//
// HINT
// Do not forget incrementing the `i` before the `continue`
// statement and at the end of the loop.
//
// EXPECTED OUTPUT
// go run main.go 1 10
// 2 + 4 + 6 + 8 + 10 = 30
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/05-break-up/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) < 3 {
fmt.Println("gimme two numbers")
return
}
min, err1 := strconv.Atoi(os.Args[1])
max, err2 := strconv.Atoi(os.Args[2])
if err1 != nil || err2 != nil || min >= max {
fmt.Println("wrong numbers")
return
}
var (
i = min
sum int
)
for {
if i > max {
break
} else if i%2 != 0 {
i++
continue
}
fmt.Print(i)
if i < max-1 {
fmt.Print(" + ")
}
sum += i
i++
}
fmt.Printf(" = %d\n", sum)
}
================================================
FILE: 13-loops/exercises/05-crunch-the-primes.md
================================================
# Crunch the Primes
1. **[Crunch the primes](https://github.com/inancgumus/learngo/tree/master/13-loops/exercises/10-crunch-the-primes)**
================================================
FILE: 13-loops/exercises/06-infinite-kill/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Infinite Kill
//
// 1. Create an infinite loop
// 2. On each step of the loop print a random character.
// 3. And, sleep for 250 milliseconds.
// 4. Run the program and wait a couple of seconds
// then kill it using CTRL+C keys
//
// RESTRICTIONS
// 1. Print one of those characters randomly: \ / | -
// 2. Before printing a character print also this
// escape sequence: \r
//
// Like this: "\r/", or this: "\r|", and so on...
//
// 3. NOTE : If you're using Go Playground, use "\f" instead of "\r"
//
// HINTS
// 1. Use `time.Sleep` to sleep.
// 2. You should pass a `time.Duration` value to it.
// 3. Check out the Go online documentation for the
// `Millisecond` constant.
// 4. When printing, do not use a newline! Or a Println!
// Use Print or Printf instead.
//
// NOTE
// If this exercise is hard for you now, wait until the
// lucky number lecture. Even then so, then just skip it.
//
// You can return back to it afterwards.
//
// EXPECTED OUTPUT
// - The program should display the following messages in any order.
// - And, the first character (\, -, /, or |) should be randomly
// displayed.
// - \r or \f sequence will clear the line.
//
// \ Please Wait. Processing....
// - Please Wait. Processing....
// / Please Wait. Processing....
// | Please Wait. Processing....
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/06-infinite-kill/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
for {
var c string
switch rand.Intn(4) {
case 0:
c = "\\"
case 1:
c = "/"
case 2:
c = "|"
case 3:
c = "-"
}
fmt.Printf("\r%s Please Wait. Processing....", c)
time.Sleep(time.Millisecond * 250)
}
}
================================================
FILE: 13-loops/exercises/07-multiplication-table-exercises/01-dynamic-table/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Dynamic Table
//
// Get the size of the table from the command-line
// Passing 5 should create a 5x5 table
// Passing 10 for a 10x10 table
//
// RESTRICTION
// Solve this exercise without looking at the original
// multiplication table exercise.
//
// HINT
// There was a max constant in the original program.
// That determines the size of the table.
//
// EXPECTED OUTPUT
//
// go run main.go
// Give me the size of the table
//
// go run main.go -5
// Wrong size
//
// go run main.go ABC
// Wrong size
//
// go run main.go 1
// X 0 1
// 0 0 0
// 1 0 1
//
// go run main.go 2
// X 0 1 2
// 0 0 0 0
// 1 0 1 2
// 2 0 2 4
//
// go run main.go 3
// X 0 1 2 3
// 0 0 0 0 0
// 1 0 1 2 3
// 2 0 2 4 6
// 3 0 3 6 9
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/07-multiplication-table-exercises/01-dynamic-table/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
args := os.Args
if len(args) != 2 {
fmt.Println("Give me the size of the table")
return
}
size, err := strconv.Atoi(args[1])
if err != nil || size <= 0 {
fmt.Println("Wrong size")
return
}
// print the header
fmt.Printf("%5s", "X")
for i := 0; i <= size; i++ {
fmt.Printf("%5d", i)
}
fmt.Println()
for i := 0; i <= size; i++ {
// print the vertical header
fmt.Printf("%5d", i)
// print the cells
for j := 0; j <= size; j++ {
fmt.Printf("%5d", i*j)
}
fmt.Println()
}
}
================================================
FILE: 13-loops/exercises/07-multiplication-table-exercises/02-math-tables/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Math Tables
//
// Create division, addition and subtraction tables
//
// 1. Get the math operation and
// the size of the table from the user
//
// 2. Print the table accordingly
//
// 3. Correctly handle the division by zero error
//
//
// BONUS #1
//
// Use strings.IndexAny function to detect
// the valid operations.
//
// Search on Google for: golang pkg strings IndexAny
//
// BONUS #2
//
// Add remainder operation as well (remainder table using %).
//
//
// EXPECTED OUTPUT
//
// go run main.go
// Usage: [op=*/+-] [size]
//
// go run main.go "*"
// Size is missing
// Usage: [op=*/+-] [size]
//
// go run main.go "%" 4
// Invalid operator.
// Valid ops one of: */+-
//
// go run main.go "*" 4
// * 0 1 2 3 4
// 0 0 0 0 0 0
// 1 0 1 2 3 4
// 2 0 2 4 6 8
// 3 0 3 6 9 12
// 4 0 4 8 12 16
//
// go run main.go "/" 4
// / 0 1 2 3 4
// 0 0 0 0 0 0
// 1 0 1 0 0 0
// 2 0 2 1 0 0
// 3 0 3 1 1 0
// 4 0 4 2 1 1
//
// go run main.go "+" 4
// + 0 1 2 3 4
// 0 0 1 2 3 4
// 1 1 2 3 4 5
// 2 2 3 4 5 6
// 3 3 4 5 6 7
// 4 4 5 6 7 8
//
// go run main.go "-" 4
// - 0 1 2 3 4
// 0 0 -1 -2 -3 -4
// 1 1 0 -1 -2 -3
// 2 2 1 0 -1 -2
// 3 3 2 1 0 -1
// 4 4 3 2 1 0
//
// BONUS:
//
// go run main.go "%" 4
// % 0 1 2 3 4
// 0 0 0 0 0 0
// 1 0 0 1 1 1
// 2 0 0 0 2 2
// 3 0 0 1 0 3
// 4 0 0 0 1 0
//
// NOTES:
//
// When running the program in Windows Git Bash, you might need
// to escape the characters like this.
//
// This happens because those characters have special meaning.
//
// Division:
// go run main.go // 4
//
// Multiplication and others:
// (this is also necessary for non-Windows bashes):
//
// go run main.go "*" 4
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/07-multiplication-table-exercises/02-math-tables/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
const (
validOps = "%*/+-"
usageMsg = "Usage: [op=" + validOps + "] [size]"
sizeMissingMsg = "Size is missing"
invalidOpMsg = `Invalid operator.
Valid ops one of: ` + validOps
invalidOp = -1
)
func main() {
args := os.Args[1:]
switch l := len(args); {
case l == 1:
fmt.Println(sizeMissingMsg)
fallthrough
case l < 1:
fmt.Println(usageMsg)
return
}
op := args[0]
if strings.IndexAny(op, validOps) == invalidOp {
fmt.Println(invalidOpMsg)
return
}
size, err := strconv.Atoi(args[1])
if err != nil || size <= 0 {
fmt.Println("Wrong size")
return
}
fmt.Printf("%5s", op)
for i := 0; i <= size; i++ {
fmt.Printf("%5d", i)
}
fmt.Println()
for i := 0; i <= size; i++ {
fmt.Printf("%5d", i)
for j := 0; j <= size; j++ {
var res int
switch op {
case "*":
res = i * j
case "%":
if j != 0 {
res = i % j
}
case "/":
if j != 0 {
res = i / j
}
case "+":
res = i + j
case "-":
res = i - j
}
fmt.Printf("%5d", res)
}
fmt.Println()
}
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/01-first-turn-winner/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: First Turn Winner
//
// If the player wins on the first turn, then display
// a special bonus message.
//
// RESTRICTION
// The first picked random number by the computer should
// match the player's guess.
//
// EXAMPLE SCENARIO
// 1. The player guesses 6
// 2. The computer picks a random number and it happens
// to be 6
// 3. Terminate the game and print the bonus message
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/01-first-turn-winner/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
const (
maxTurns = 5 // less is more difficult
usage = `Welcome to the Lucky Number Game! 🍀
The program will pick %d random numbers.
Your mission is to guess one of those numbers.
The greater your number is, harder it gets.
Wanna play?
`
)
func main() {
rand.Seed(time.Now().UnixNano())
args := os.Args[1:]
if len(args) != 1 {
fmt.Printf(usage, maxTurns)
return
}
guess, err := strconv.Atoi(args[0])
if err != nil {
fmt.Println("Not a number.")
return
}
if guess <= 0 {
fmt.Println("Please pick a positive number.")
return
}
for turn := 1; turn <= maxTurns; turn++ {
n := rand.Intn(guess) + 1
if n == guess {
if turn == 1 {
fmt.Println("🥇 FIRST TIME WINNER!!!")
} else {
fmt.Println("🎉 YOU WON!")
}
return
}
}
fmt.Println("☠️ YOU LOST... Try again?")
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/01-first-turn-winner/solution-better/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
const (
maxTurns = 5 // less is more difficult
usage = `Welcome to the Lucky Number Game! 🍀
The program will pick %d random numbers.
Your mission is to guess one of those numbers.
The greater your number is, harder it gets.
Wanna play?
`
)
func main() {
rand.Seed(time.Now().UnixNano())
args := os.Args[1:]
if len(args) != 1 {
fmt.Printf(usage, maxTurns)
return
}
guess, err := strconv.Atoi(args[0])
if err != nil {
fmt.Println("Not a number.")
return
}
if guess <= 0 {
fmt.Println("Please pick a positive number.")
return
}
for turn := 1; turn <= maxTurns; turn++ {
n := rand.Intn(guess) + 1
// Better, why?
//
// Instead of nesting the if statement into
// another if statement; it simply continues.
//
// TLDR: Avoid nested statements.
if n != guess {
continue
}
if turn == 1 {
fmt.Println("🥇 FIRST TIME WINNER!!!")
} else {
fmt.Println("🎉 YOU WON!")
}
return
}
fmt.Println("☠️ YOU LOST... Try again?")
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/02-random-messages/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Random Messages
//
// Display a few different won and lost messages "randomly".
//
// HINTS
// 1. You can use a switch statement to do that.
// 2. Set its condition to the random number generator.
// 3. I would use a short switch.
//
// EXAMPLES
// The Player wins: then randomly print one of these:
//
// go run main.go 5
// YOU WON
// go run main.go 5
// YOU'RE AWESOME
//
// The Player loses: then randomly print one of these:
//
// go run main.go 5
// LOSER!
// go run main.go 5
// YOU LOST. TRY AGAIN?
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/02-random-messages/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
const (
maxTurns = 5 // less is more difficult
usage = `Welcome to the Lucky Number Game! 🍀
The program will pick %d random numbers.
Your mission is to guess one of those numbers.
The greater your number is, harder it gets.
Wanna play?
`
)
func main() {
rand.Seed(time.Now().UnixNano())
args := os.Args[1:]
if len(args) != 1 {
fmt.Printf(usage, maxTurns)
return
}
guess, err := strconv.Atoi(args[0])
if err != nil {
fmt.Println("Not a number.")
return
}
if guess <= 0 {
fmt.Println("Please pick a positive number.")
return
}
for turn := 0; turn < maxTurns; turn++ {
n := rand.Intn(guess) + 1
if n == guess {
switch rand.Intn(3) {
case 0:
fmt.Println("🎉 YOU WIN!")
case 1:
fmt.Println("🎉 YOU'RE AWESOME!")
case 2:
fmt.Println("🎉 PERFECT!")
}
return
}
}
msg := "%s Try again?\n"
switch rand.Intn(2) {
case 0:
fmt.Printf(msg, "☠️ YOU LOST...")
case 1:
fmt.Printf(msg, "☠️ JUST A BAD LUCK...")
}
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/03-double-guesses/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Double Guesses
//
// Let the player guess two numbers instead of one.
//
// HINT:
// Generate random numbers using the greatest number
// among the guessed numbers.
//
// EXAMPLES
// go run main.go 5 6
// Player wins if the random number is either 5 or 6.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/03-double-guesses/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
const (
maxTurns = 5 // less is more difficult
usage = `Welcome to the Lucky Number Game! 🍀
The program will pick %d random numbers.
Your mission is to guess one of those numbers.
The greater your number is, harder it gets.
Wanna play?
`
)
func main() {
rand.Seed(time.Now().UnixNano())
args := os.Args[1:]
if len(args) < 1 {
fmt.Printf(usage, maxTurns)
return
}
guess, err := strconv.Atoi(args[0])
if err != nil {
fmt.Println("Not a number.")
return
}
var guess2 int
if len(args) == 2 {
guess2, err = strconv.Atoi(args[1])
if err != nil {
fmt.Println("Not a number.")
return
}
}
if guess <= 0 || guess2 <= 0 {
fmt.Println("Please pick positive numbers.")
return
}
min := guess
if guess < guess2 {
min = guess2
}
for turn := 0; turn < maxTurns; turn++ {
n := rand.Intn(min) + 1
if n == guess || n == guess2 {
fmt.Println("🎉 YOU WIN!")
return
}
}
fmt.Println("☠️ YOU LOST... Try again?")
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/04-verbose-mode/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Verbose Mode
//
// When the player runs the game like this:
//
// go run main.go -v 4
//
// Display each generated random number:
// 1 3 4 🎉 YOU WIN!
//
// In this example, computer picks 1, 3, and 4. And the
// player wins.
//
// HINT
// You need to get and interpret the command-line arguments.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/04-verbose-mode/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
const (
maxTurns = 5 // less is more difficult
usage = `Welcome to the Lucky Number Game! 🍀
The program will pick %d random numbers.
Your mission is to guess one of those numbers.
The greater your number is, harder it gets.
Wanna play?
(Provide -v flag to see the picked numbers.)
`
)
func main() {
rand.Seed(time.Now().UnixNano())
args := os.Args[1:]
if len(args) < 1 {
fmt.Printf(usage, maxTurns)
return
}
var verbose bool
if args[0] == "-v" {
verbose = true
}
guess, err := strconv.Atoi(args[len(args)-1])
if err != nil {
fmt.Println("Not a number.")
return
}
if guess <= 0 {
fmt.Println("Please pick a positive number.")
return
}
for turn := 1; turn <= maxTurns; turn++ {
n := rand.Intn(guess) + 1
if verbose {
fmt.Printf("%d ", n)
}
if n == guess {
if turn == 1 {
fmt.Println("🥇 FIRST TIME WINNER!!!")
} else {
fmt.Println("🎉 YOU WON!")
}
return
}
}
fmt.Println("☠️ YOU LOST... Try again?")
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/05-enough-picks/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Enough Picks
//
// If the player's guess number is below 10;
// then make sure that the computer generates a random
// number between 0 and 10.
//
// However, if the guess number is above 10; then the
// computer should generate the numbers
// between 0 and the guess number.
//
// WHY?
// This way the game will be harder.
//
// Because, in the current version of the game, if
// the player's guess number is for example 3; then the
// computer picks a random number between 0 and 3.
//
// So, currently a player can easily win the game.
//
// EXAMPLE
// Suppose that the player runs the game like this:
// go run main.go 9
//
// Or like this:
// go run main.go 2
//
// Then the computer should pick a random number
// between 0-10.
//
// Or, if the player runs it like this:
// go run main.go 15
//
// Then the computer should pick a random number
// between 0-15.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/05-enough-picks/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
const (
maxTurns = 5 // less is more difficult
usage = `Welcome to the Lucky Number Game! 🍀
The program will pick %d random numbers.
Your mission is to guess one of those numbers.
The greater your number is, harder it gets.
Wanna play?
`
)
func main() {
rand.Seed(time.Now().UnixNano())
args := os.Args[1:]
if len(args) < 1 {
fmt.Printf(usage, maxTurns)
return
}
guess, err := strconv.Atoi(args[0])
if err != nil {
fmt.Println("Not a number.")
return
}
if guess <= 0 {
fmt.Println("Please pick a positive number.")
return
}
min := 10
if guess > min {
min = guess
}
for turn := 0; turn < maxTurns; turn++ {
n := rand.Intn(min) + 1
if n == guess {
fmt.Println("🎉 YOU WIN!")
return
}
}
fmt.Println("☠️ YOU LOST... Try again?")
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/06-dynamic-difficulty/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Dynamic Difficulty
//
// Current game picks only 5 numbers (5 turns).
//
// Make sure that the game adjust its own difficulty
// depending on the guess number.
//
// RESTRICTION
// Do not make the game too easy. Only adjust the
// difficulty if the guess is above 10.
//
// EXPECTED OUTPUT
// Suppose that the player runs the game like this:
// go run main.go 5
//
// Then the computer should pick 5 random numbers.
//
// Or, if the player runs it like this:
// go run main.go 25
//
// Then the computer may pick 11 random numbers
// instead.
//
// Or, if the player runs it like this:
// go run main.go 100
//
// Then the computer may pick 30 random numbers
// instead.
//
// As you can see, greater guess number causes the
// game to increase the game turns, which in turn
// adjust the game's difficulty dynamically.
//
// Because, greater guess number makes it harder to win.
// But, this way, game's difficulty will be dynamic.
// It will adjust its own difficulty depending on the
// guess number.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/08-lucky-number-exercises/06-dynamic-difficulty/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
const (
maxTurns = 5 // less is more difficult
usage = `Welcome to the Lucky Number Game! 🍀
The program will pick %d random numbers.
Your mission is to guess one of those numbers.
The greater your number is, harder it gets.
Wanna play?
`
)
func main() {
rand.Seed(time.Now().UnixNano())
args := os.Args[1:]
if len(args) != 1 {
fmt.Printf(usage, maxTurns)
return
}
guess, err := strconv.Atoi(args[0])
if err != nil {
fmt.Println("Not a number.")
return
}
if guess <= 0 {
fmt.Println("Please pick a positive number.")
return
}
var balancer int
if guess > 10 {
balancer = guess / 4
}
for turn := maxTurns + balancer; turn > 0; turn-- {
n := rand.Intn(guess) + 1
if n == guess {
fmt.Println("🎉 YOU WIN!")
return
}
}
fmt.Println("☠️ YOU LOST... Try again?")
}
================================================
FILE: 13-loops/exercises/09-word-finder-exercises/01-case-insensitive/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Case Insensitive Search
//
// Allow for case-insensitive searching
//
// EXAMPLE
// Let's say that the user runs the program like this:
// go run main.go LAZY
//
// Or like this: go run main.go lAzY
// Or like this: go run main.go lazy
//
// For all cases above, the program should find
// the "lazy" keyword.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/09-word-finder-exercises/01-case-insensitive/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
const corpus = "lazy cat jumps again and again and again"
func main() {
words := strings.Fields(corpus)
query := os.Args[1:]
queries:
for _, q := range query {
// case insensitive search
q = strings.ToLower(q)
search:
for i, w := range words {
switch q {
case "and", "or", "the":
break search
}
if q == w {
fmt.Printf("#%-2d: %q\n", i+1, w)
continue queries
}
}
}
}
================================================
FILE: 13-loops/exercises/09-word-finder-exercises/02-path-searcher/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Path Searcher
//
// Your program should search inside the path environment
// variable.
//
// Remove the corpus constant then get the corpus from the
// environment variable "Path" or "PATH".
//
// HINTS
// 1. Search the web to find out what is an environment
// variable and how to use it (if you don't know
// what it is already).
//
// 2. Look up for the necessary functions for getting
// an environment variable. It's in the "os" package.
//
// Search for it on the Go online documentation.
//
// 3. Look up for the necessary function for splitting
// the path variable into directory names.
//
// It's in the "path/filepath" package.
//
// EXAMPLE
// For example, on my Mac, my PATH environment variable
// looks like this:
//
// "/usr/local/bin:/sbin:/Users/inanc/go/bin"
//
// So, if the user runs the program like this:
//
// go run main.go /sbin
//
// It should print this:
//
// #2 : "/sbin"
// ---------------------------------------------------------
// ---------------------------------------------------------
// BONUS EXERCISE
// Make your program cross platform. So, it can search
// the path environment variable when you run it on
// a Windows or on a Mac (OS X) or on a Linux.
//
// BONUS EXERCISE #2
// Also find the directories for the directories that
// contains the searched query.
//
// And let it match in a case-insensitive manner. See the examples.
//
// EXAMPLE:
// Let's say:
// PATH="/usr/local/bin:/sbin:/Users/inanc/go/bin"
//
// So, if the user runs the program like this:
// go run main.go bin
//
// It should print this:
// #1 : "/usr/local/bin"
// #2 : "/sbin"
// #3 : "/Users/inanc/go/bin"
//
// Or like this (case insensitive):
// go run main.go Us
//
// Output:
// #1 : "/usr/local/bin"
// #2 : "/Users/inanc/go/bin"
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/09-word-finder-exercises/02-path-searcher/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
)
func main() {
// Get and split the PATH environment variable
// SplitList function automatically finds the
// separator for the path env variable
words := filepath.SplitList(os.Getenv("PATH"))
// Alternative way, but above one is better:
// words := strings.Split(
// os.Getenv("PATH"),
// string(os.PathListSeparator))
query := os.Args[1:]
for _, q := range query {
for i, w := range words {
q, w = strings.ToLower(q), strings.ToLower(w)
if strings.Contains(w, q) {
fmt.Printf("#%-2d: %q\n", i+1, w)
}
}
}
}
================================================
FILE: 13-loops/exercises/10-crunch-the-primes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Crunch the primes
//
// 1. Get numbers from the command-line.
// 2. `for range` over them.
// 4. Convert each one to an int.
// 5. If one of the numbers isn't an int, just skip it.
// 6. Print the ones that are only the prime numbers.
//
// RESTRICTION
// The user can run the program with any number of
// arguments.
//
// HINT
// Find whether a number is prime using this algorithm:
// https://stackoverflow.com/a/1801446/115363
//
// EXPECTED OUTPUT
// go run main.go 2 4 6 7 a 9 c 11 x 12 13
// 2 7 11 13
//
// go run main.go 1 2 3 5 7 A B C
// 2 3 5 7
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 13-loops/exercises/10-crunch-the-primes/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// remember [1:] skips the first argument
main:
for _, arg := range os.Args[1:] {
n, err := strconv.Atoi(arg)
if err != nil {
// skip non-numerics
continue
}
switch {
// prime
case n == 2 || n == 3:
fmt.Print(n, " ")
continue
// not a prime
case n <= 1 || n%2 == 0 || n%3 == 0:
continue
}
for i, w := 5, 2; i*i <= n; {
// not a prime
if n%i == 0 {
continue main
}
i += w
w = 6 - w
}
// all checks ok: it's a prime
fmt.Print(n, " ")
}
fmt.Println()
}
================================================
FILE: 13-loops/exercises/README.md
================================================
There are 17 exercises in this section.
You can find them inside the subdirectories.
================================================
FILE: 13-loops/questions/01-loops.md
================================================
## Which one of these is a valid loop statement in Go?
1. while
2. forever
3. until
4. for *CORRECT*
> **4:** Correct. There is only one loop statement in Go.
## What does this code print?
```go
for i := 3; i > 0; i-- {
fmt.Println(i)
}
```
1. 3 2 1 *CORRECT*
2. 1 2 3
3. 0 1 2
4. 2 1 0
## What does this code print?
```go
for i := 3; i > 0; {
i--
fmt.Println(i)
}
```
1. 3 2 1
2. 1 2 3
3. 0 1 2
4. 2 1 0 *CORRECT*
## What does this code print?
```go
for i := 3; ; {
if i <= 0 {
break
}
i--
fmt.Println(i)
}
```
1. 3 2 1
2. 1 2 3
3. 0 1 2
4. 2 1 0 *CORRECT*
## What does this code print?
```go
for i := 2; i <= 9; i++ {
if i % 3 != 0 {
continue
}
fmt.Println(i)
}
```
1. 3 6 9 *CORRECT*
2. 9 6 3
3. 2 3 6 9
4. 2 3 4 5 6 7 8 9
## How can you simplify this code?
```go
for ; true ; {
// ...
}
```
1. ```go
for true {
}
```
2. ```go
for true; {
}
```
3. ```go
for {
}
```
*CORRECT*
4. ```go
for ; true {
}
```
## What does this code print?
Let's say that you run the program like this:
```bash
go run main.go go is awesome
```
```go
for i, v := range os.Args[1:] {
fmt.Println(i+1, v)
}
```
1. ```
1 go
2 is
3 awesome
```
*CORRECT*
2. ```
go
is
awesome
```
3. ```
0 go
1 is
2 awesome
```
4. ```
1
2
3
```
## What does this code print?
Let's say that you run the program like this:
```bash
go run main.go go is awesome
```
```go
for i := range os.Args[1:] {
fmt.Println(i+1)
}
```
1. ```
1 go
2 is
3 awesome
```
2. ```
go
is
awesome
```
3. ```
0 go
1 is
2 awesome
```
4. ```
1
2
3
```
*CORRECT*
## What does this code print?
Let's say that you run the program like this:
```bash
go run main.go go is awesome
```
```go
for _, v := range os.Args[1:] {
fmt.Println(v)
}
```
1. ```
1 go
2 is
3 awesome
```
2. ```
go
is
awesome
```
*CORRECT*
3. ```
0 go
1 is
2 awesome
```
4. ```
1
2
3
```
## What does this code print?
Let's say that you run the program like this:
```bash
go run main.go go is awesome
```
```go
var i int
for range os.Args {
i++
}
fmt.Println(i)
```
1. go is awesome
2. 1 2 3
3. 2
4. 4 *CORRECT*
> **4:** As you can see, you can also use a for range statement for counting things.
================================================
FILE: 13-loops/questions/02-randomization.md
================================================
## What's pseudorandom number generation?
1. Numbers appear to be randomly generated but in reality they are not *CORRECT*
2. Generating random numbers according to the physical laws
3. Generating pseudo even and odd numbers
> **1:** Computers are deterministic machines. They can't generate truly random numbers (unlike actual physical processes).
## What's a seed number?
1. Exchanging of random numbers between two computers
2. It's used to getting a random number between 0 and the seed number
3. It's used initialize a pseduorandom number generator *CORRECT*
## Which package is used to generate pseudorandom numbers in Go?
1. pseudorand
2. rand *CORRECT*
3. random
4. randomizer
## What does [0, 5) mean?
1. A range of numbers between 0 and 5 (excluding 5) *CORRECT*
2. A range of numbers between 0 and 5 (including 5)
3. Just 0 and 5
4. Just 0 and 4
> **1:** Right. The square-brace means: "inclusion". The parenthesis means: "exclusion". So, [0, 5] means: 0, 1, 2, 3, 4. It's called the "mathematical interval notation".
## Why this function call would not work?
```go
rand.Intn(0)
```
1. First you should seed it
2. It expects two arguments
3. Intn works within a range of [0, 0). So, it doesn't make sense to include 0 and not include 0 at the same time. *CORRECT*
> **1:** That's not the cause of this error. You don't always have to seed it.
> **2:** No, it does not.
## What does this program print?
Note that, each seed number below returns pseudorandom numbers as these:
```
Seed: 0
3 3 6 8 4 1 9 3 6 6
Seed: 1
1 1 9 3 2 4 7 6 6 6
Seed: 2
10 1 2 2 0 6 4 1 0 5
```
Here's the program:
```go
package main
import (
"fmt"
"math/rand"
)
func main() {
for i := 0; i < 3; i++ {
rand.Seed(int64(i))
fmt.Print(rand.Intn(11), " ")
fmt.Print(rand.Intn(11), " ")
}
}
```
1. 3 1 10 3 1 1
2. 3 6 1 6 10 5
3. 1 10 1 1 3 3
4. 3 3 1 1 10 1 *CORRECT*
> **4:** The numbers are determined depending on the seed number. So, this loop, seeds the pseudorandom generator with 0, 1, and 2 respectively.
>
> And, after each seed, it calls Intn twice to generate two random numbers.
>
> So, if you look at the result, 3 3 is the first two numbers of Seed: 0. 1 1 for Seed: 1. And, 10 1 for Seed: 2.
## What you should do if you want the pseudorandom generator to produce random numbers each time you run your program?
1. You need to seed it like this: rand.Seed(rand.Random)
2. You need to seed it like this: rand.Seed(time.Now().UnixNano()) *CORRECT*
3. You need to seed it like this: rand.Seed(time.Now())
================================================
FILE: 13-loops/questions/03-labeled-statements.md
================================================
## Which scope a label belongs to?
1. To the scope of the statement that it is in
2. To the body of the function that it is in *CORRECT*
3. To the package scope that it is in
> **1:** Labels do not belong to statement scopes unlike other names like variable or constant names.
>
> **2:** They can be used throughout the function, even before their declaration inside the function. This also what makes goto statement jump to any label within a function.
## There two for loop statements below and a label called "words". Which statement does the "words label" label?"
```go
for range words {
words:
for range letters {
// ...
}
}
```
1. The first loop
2. The second, nested loop *CORRECT*
3. All the loops
> **2:** A label can only label one statement at a time.
## Will this loop terminate after the break?
**BTW:** _"terminate" is the same thing with "quit". Remember, statements can also terminate. This means that the statement will end. It doesn't mean that the program will end._
```go
package main
func main() {
main:
for {
switch "A" {
case "A":
break // <- here!
case "B":
continue main
}
}
}
```
1. No, the break will only terminate the switch but the loop will continue *CORRECT*
2. Yes, the break will terminate the loop
3. Yes, the break will terminate the switch
> **1:** Yep. This is an unlabeled break. So, it breaks the closest statement, which in here, it's that switch statement. And, since it only breaks the switch, the loop will keep continue.
>
> **3:** Yep. However, why would that kill the loop as well?
## Will this loop ever terminate?
```go
package main
func main() {
flag := "A"
main:
for {
switch flag {
case "A":
flag = "B"
break
case "B":
break main
}
}
}
```
1. No, this loop will loop to infinity
2. Yes, the first break will terminate the loop
3. Yes, the second break will terminate the loop *CORRECT*
> **2:** No it does not but it helps.
>
> **3:** Yep. Do you know why? Because, at first, first case will match, and it will set the flag to "B". So, in the next loop step, the 2nd case will be hit, then, it will break from the loop, because the loop is labeled with the main label.
## What the first break below does?
Note that, in this program, there's an infinite loop.
```go
package main
func main() {
for {
switcher:
switch 1 {
case 1:
switch 2 {
case 2:
break switcher
}
}
break
}
}
```
1. It breaks from the 2nd switch causing the program will loop indefinitely
2. It breaks from the 2nd switch and then the 2nd break will terminate the loop
3. It breaks from the 1st switch and then the 2nd break will terminate the loop *CORRECT*
> **1:** There's another break after the switch, so the loop will end immediately.
>
> **2:** It doesn't break the 2nd switch. The label labels the 1st switch.
## What's wrong with this program?
```go
package main
func main() {
for {
switcher:
switch {
case true:
switch {
case false:
continue switcher
}
}
}
}
```
1. continue statement can only continue a loop *CORRECT*
2. continue statement cannot be used within a switch statement
3. It will loop to infinity
> **1:** Yes! Here, the switcher label labels the first switch statement. So, it's a switch label. And, then it tries to jump to that label using a continue. However, a continue statement can only be used to jump to a loop label.
>
> **2:** Yes, it can be used in a switch statement to continue for the next loop step. But, that's not the problem with this program.
>
> **3:** Yes, but that's not the real problem.
## Which one of these programs will terminate?
I mean: When you run it, which one will quit. Some of the codes here will indefinitely run.
1. ```go
func main() {
start: goto exit
exit : fmt.Println("exiting")
goto start
}
```
2. ```go
func main() {
exit: fmt.Println("exiting")
goto exit
}
```
3. ```go
func main() {
goto exit
start : goto getout
exit : goto start
getout: fmt.Println("exiting")
}
```
*CORRECT*
> **1:** In the start label: "goto exit" sends the execution to the exit label. In the exit label: "goto start" sends the execution back to the start label. So, it's an infinite loop. The program will never terminate.
>
> **2:** In the exit label: "goto exit" sends the execution back to the exit label. So, it's an infinite loop. The program will never terminate.
>
> **3:** "goto exit" sends the execution to the exit label. In the exit label: "goto start" sends the execution to the start label. In the start label: "goto getout" sends the execution to the getout label. And, since the getout label is the last statement of the main function, the program will terminate there.
================================================
FILE: 14-arrays/01-whats-an-array/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
myAge byte
herAge byte
// this declares an array with two byte elements
// its length : 2
// its element type: byte
ages [2]byte
// this declares an array with five string elements
// its length : 5
// its element type: string
tags [5]string
// this array doesn't occupy any memory space (its length is zero)
// its length : 0
// its element type: byte
zero [0]byte
// this array uses a constant expression
// its length : 3
// its element type: byte
agesExp [2 + 1]byte
// uncomment the code below and observe the error
//
// wrongDeclaration [-1]byte
)
fmt.Printf("myAge : %d\n", myAge)
fmt.Printf("herAge : %d\n", herAge)
// Since arrays we've declared here don't have any elements,
// Go automatically sets all their elements to their zero values
// depending on their element type.
// #v verb prints the array's length, element type and its elements
fmt.Printf("ages : %#v\n", ages)
fmt.Printf("tags : %#v\n", tags)
fmt.Printf("zero : %#v\n", zero)
fmt.Printf("agesExp : %#v\n", agesExp)
// note:
// ages and agesExp get printed 0x0 because they're byte arrays.
// bytes are represented with hex values. 0x0 means 0.
// =========================================================================
// GETTING AND SETTING ARRAY ELEMENTS
// =========================================================================
// Note:
//
// Since, I've already declared the ages variable above,
// and, to show you the example below, I needed to create a new block.
//
// ages variable below is in a new block below. So, it's a new variable.
//
// I did so because I need to change the element type of the ages array
// to int (or, subtracting from a byte results in wraparound).
{
var ages [2]int
fmt.Println()
fmt.Printf("ages : %#v\n", ages)
fmt.Printf("ages's type : %T\n", ages)
fmt.Println("len(ages) :", len(ages))
fmt.Println("ages[0] :", ages[0])
fmt.Println("ages[1] :", ages[1])
fmt.Println("ages[len(ages)-1] :", ages[len(ages)-1])
// WRONG:
// fmt.Println("ages[-1] :", ages[-1])
// fmt.Println("ages[2] :", ages[2])
// fmt.Println("ages[len(ages)] :", ages[len(ages)])
ages[0] = 6
ages[1] -= 3
// WRONG:
// ages[0] = "Can I?"
fmt.Println("ages[0] :", ages[0])
fmt.Println("ages[1] :", ages[1])
ages[0] *= ages[1]
fmt.Println("ages[0] :", ages[0])
fmt.Println("ages[1] :", ages[1])
}
}
================================================
FILE: 14-arrays/02-examples-1-hipsters-love-bookstore/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// STORY:
// Hipster's Love store publishes limited books
// twice a year.
//
// The number of books they publish is fixed at 4.
// So, let's create a 4 elements string array for the books.
const (
winter = 1
summer = 3
yearly = winter + summer
)
func main() {
// var books [4]string
// var books [1 + 3]string
var books [yearly]string
books[0] = "Kafka's Revenge"
books[1] = "Stay Golden"
books[2] = "Everythingship"
books[3] += books[0] + " 2nd Edition"
// --------------------
// INDEXING
// --------------------
// Go compiler can catch indexing errors when constant is used
// books[4] = "Neverland"
// Go compiler cannot catch indexing errors when non-constant is used
// i := 4
// books[i] = "Neverland"
// --------------------
// PRINTING ARRAYS
// --------------------
// print the type
fmt.Printf("books : %T\n", books)
// print the elements
fmt.Println("books :", books)
// print the elements in quoted string
fmt.Printf("books : %q\n", books)
// print the elements along with their types
fmt.Printf("books : %#v\n", books)
}
================================================
FILE: 14-arrays/03-examples-2-hipsters-love-bookstore/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// STORY:
// Hipster's Love store publishes limited books
// twice a year.
//
// The number of books they publish is fixed at 4.
// So, let's create a 4 elements string array for the books.
const (
winter = 1
summer = 3
yearly = winter + summer
)
func main() {
var books [yearly]string
books[0] = "Kafka's Revenge"
books[1] = "Stay Golden"
books[2] = "Everythingship"
books[3] += books[0] + " 2nd Edition"
fmt.Printf("books : %#v\n", books)
// ------------------------------------
// SEASONAL BOOKS
// ------------------------------------
var (
wBooks [winter]string
sBooks [summer]string
)
// assign the first book as the wBook's first book
wBooks[0] = books[0]
// assign all the books starting from the 2nd book
// to sBooks array
// sBooks[0] = books[1]
// sBooks[1] = books[2]
// sBooks[2] = books[3]
// for i := 0; i < len(sBooks); i++ {
// sBooks[i] = books[i+1]
// }
for i := range sBooks {
sBooks[i] = books[i+1]
// changes to sBooks[i] will not be visible here.
// sBooks here is a copy of the original array.
}
// changes to sBooks are visible here
// sBooks is a copy of the original sBooks array.
//
// v is also a copy of the original array element.
//
// if you want to update the original element, use it as in the loop above.
//
// for _, v := range sBooks {
// v += "won't effect"
// }
fmt.Printf("\nwinter : %#v\n", wBooks)
fmt.Printf("\nsummer : %#v\n", sBooks)
// ------------------------------------
// Let's print the published books
// ------------------------------------
// equal to: [4]bool
var published [len(books)]bool
published[0] = true
published[len(books)-1] = true
fmt.Println("\nPublished Books:")
for i, ok := range published {
if ok {
fmt.Printf("+ %s\n", books[i])
}
}
}
================================================
FILE: 14-arrays/04-array-literal/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// STORY:
// Hipster's Love store publishes limited books
// twice a year.
//
// The number of books they publish is fixed at 4.
// So, let's create a 4 elements string array for the books.
func main() {
// Use this only when you don't know about the elements beforehand
{
var books [4]string
books[0] = "Kafka's Revenge"
books[1] = "Stay Golden"
books[2] = "Everythingship"
books[3] += "Kafka's Revenge 2nd Edition"
_ = books
}
// This is not necessary, use the short declaration syntax below
{
var books = [4]string{
"Kafka's Revenge",
"Stay Golden",
"Everythingship",
"Kafka's Revenge 2nd Edition",
}
_ = books
}
// Use this if you know about the elements
{
books := [4]string{
"Kafka's Revenge",
"Stay Golden",
"Everythingship",
"Kafka's Revenge 2nd Edition",
}
_ = books
}
{
// Use this if you know about the elements
books := [4]string{
"Kafka's Revenge",
"Stay Golden",
}
// Uninitialized elements will be set to their zero values
fmt.Printf("books : %#v\n", books)
}
// You can also use the ellipsis syntax
// ... equals to 4
{
books := [...]string{
"Kafka's Revenge",
"Stay Golden",
"Everythingship",
"Kafka's Revenge 2nd Edition",
}
_ = books
}
}
================================================
FILE: 14-arrays/05-examples-3-hipsters-love-bookstore/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// STORY:
// Hipster's Love store publishes limited books
// twice a year.
//
// The number of books they publish is fixed at 4.
// So, let's create a 4 elements string array for the books.
const (
winter = 1
summer = 3
yearly = winter + summer
)
func main() {
books := [...]string{
"Kafka's Revenge",
"Stay Golden",
"Everythingship",
"Kafka's Revenge 2nd Edition",
}
fmt.Printf("books : %#v\n", books)
}
================================================
FILE: 14-arrays/06-challenge-moodly/challenge/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Moodly
//
// 1. Get username from command-line
//
// 2. Display the usage if the username is missing
//
// 3. Create an array
// 1. Add three positive mood messages
// 2. Add three negative mood messages
//
// 4. Randomly select and print one of the mood messages
//
// EXPECTED OUTPUT
//
// go run main.go
// [your name]
//
// go run main.go Socrates
// Socrates feels good 👍
//
// go run main.go Socrates
// Socrates feels bad 👎
//
// go run main.go Socrates
// Socrates feels sad 😞
//
// go run main.go Socrates
// Socrates feels happy 😀
//
// go run main.go Socrates
// Socrates feels awesome 😎
//
// go run main.go Socrates
// Socrates feels terrible 😩
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/06-challenge-moodly/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"time"
)
func main() {
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("[your name]")
return
}
name := args[0]
moods := [...]string{
"happy 😀", "good 👍", "awesome 😎",
"sad 😞", "bad 👎", "terrible 😩",
}
rand.Seed(time.Now().UnixNano())
n := rand.Intn(len(moods))
fmt.Printf("%s feels %s\n", name, moods[n])
}
// inspired from:
// https://github.com/moby/moby/blob/1fd7e4c28d3a4a21c3540f03a045f96a4190b527/pkg/namesgenerator/names-generator.go
================================================
FILE: 14-arrays/07-compare/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// STORY:
// You want to compare two bookcases,
// whether they're equal or not.
func main() {
// When comparing two arrays, their types should be identical
// Comment out one of the following pair of variables and observe the results.
var (
// equal (types + elements are identical)::
blue = [3]int{6, 9, 3}
red = [3]int{6, 9, 3}
// equal (types + elements are identical):
// blue = [...]int{6, 9, 3}
// red = [3]int{6, 9, 3}
// not equal (element ordering are different):
// blue = [3]int{6, 9, 3}
// red = [3]int{3, 9, 6}
// not equal (the last elements are not equal):
// blue = [3]int{6, 9}
// red = [3]int{6, 9, 3}
// not comparable (type mismatch: length):
// blue = [3]int{6, 9, 3}
// red = [5]int{6, 9, 3}
// not comparable (type mismatch: element type):
// blue = [3]int64{6, 9, 3}
// red = [3]int{6, 9, 3}
)
fmt.Printf("blue bookcase : %v\n", blue)
fmt.Printf("red bookcase : %v\n", red)
fmt.Println("Are they equal?", blue == red)
}
================================================
FILE: 14-arrays/08-assignment/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
blue := [3]int{6, 9, 3}
red := blue
blue[0] = 10
fmt.Printf("blue: %#v\n", blue)
fmt.Printf("red : %#v\n", red)
// UNASSIGNABLE:
// blue := [3]int{6, 9, 3}
// red := [2]int{3, 5}
// red = blue
}
================================================
FILE: 14-arrays/08-assignment/02-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
prev := [3]string{"Kafka's Revenge", "Stay Golden", "Everythingship"}
// You can't do this:
// books = prev
var books [4]string
for i, b := range prev {
books[i] += b + " 2nd Ed."
}
books[3] = "Awesomeness"
fmt.Printf("last year:\n%#v\n", prev)
fmt.Printf("\nthis year:\n%#v\n", books)
}
================================================
FILE: 14-arrays/09-multi-dimensional/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// ------------------------------------
// #1 - THE BEST WAY
// ------------------------------------
students := [...][3]float64{
{5, 6, 1},
{9, 8, 4},
}
var sum float64
for _, grades := range students {
for _, grade := range grades {
sum += grade
}
}
const N = float64(len(students) * len(students[0]))
fmt.Printf("Avg Grade: %g\n", sum/N)
// ------------------------------------
// #2 - SO SO WAY
// ------------------------------------
// // You don't need to define the types for the inner arrays
// students := [2][3]float64{
// [3]float64{5, 6, 1},
// [3]float64{9, 8, 4},
// }
// var sum float64
// sum += students[0][0] + students[0][1] + students[0][2]
// sum += students[1][0] + students[1][1] + students[1][2]
// const N = float64(len(students) * len(students[0]))
// fmt.Printf("Avg Grade: %g\n", sum/N)
// ------------------------------------
// #3 - MANUAL WAY
// ------------------------------------
// student1 := [3]float64{5, 6, 1}
// student2 := [3]float64{9, 8, 4}
// var sum float64
// sum += student1[0] + student1[1] + student1[2]
// sum += student2[0] + student2[1] + student2[2]
// const N = float64(len(student1) * 2)
// fmt.Printf("Avg Grade: %g\n", sum/N)
}
================================================
FILE: 14-arrays/10-challenge-moodly-2/challenge/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"time"
)
// ---------------------------------------------------------
// EXERCISE: Moodly #2
//
// This challenge is based on the previous Moodly challenge.
//
// 1. Display the usage if the username or the mood is missing
//
// 2. Change the moods array to a multi-dimensional array.
//
// So, create two inner arrays:
// 1. One for positive moods
// 2. Another one for negative moods
//
// 4. Randomly select and print one of the mood messages depending
// on the given mood command-line argument.
//
// EXPECTED OUTPUT
//
// go run main.go
// [your name] [positive|negative]
//
// go run main.go Socrates
// [your name] [positive|negative]
//
// go run main.go Socrates positive
// Socrates feels good 👍
//
// go run main.go Socrates positive
// Socrates feels happy 😀
//
// go run main.go Socrates positive
// Socrates feels awesome 😎
//
// go run main.go Socrates negative
// Socrates feels bad 👎
//
// go run main.go Socrates negative
// Socrates feels sad 😞
//
// go run main.go Socrates negative
// Socrates feels terrible 😩
// ---------------------------------------------------------
func main() {
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("[your name]")
return
}
name := args[0]
moods := [...]string{
"happy 😀", "good 👍", "awesome 😎",
"sad 😞", "bad 👎", "terrible 😩",
}
rand.Seed(time.Now().UnixNano())
n := rand.Intn(len(moods))
fmt.Printf("%s feels %s\n", name, moods[n])
}
================================================
FILE: 14-arrays/10-challenge-moodly-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"time"
)
func main() {
args := os.Args[1:]
if len(args) != 2 {
fmt.Println("[your name] [positive|negative]")
return
}
name, mood := args[0], args[1]
moods := [...][3]string{
{"happy 😀", "good 👍", "awesome 😎"},
{"sad 😞", "bad 👎", "terrible 😩"},
}
rand.Seed(time.Now().UnixNano())
n := rand.Intn(len(moods[0]))
var mi int
if mood != "positive" {
mi = 1
}
fmt.Printf("%s feels %s\n", name, moods[mi][n])
}
================================================
FILE: 14-arrays/11-keyed-elements/01-unkeyed/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
rates := [3]float64{
0.5,
2.5,
1.5,
}
fmt.Println(rates)
}
================================================
FILE: 14-arrays/11-keyed-elements/02-keyed/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
rates := [3]float64{
0: 0.5, // index: 0
1: 2.5, // index: 1
2: 1.5, // index: 2
}
fmt.Println(rates)
// above array literal equals to this:
//
// rates := [3]float64{
// 0.5,
// 2.5,
// 1.5,
// }
}
================================================
FILE: 14-arrays/11-keyed-elements/03-keyed-order/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
rates := [3]float64{
1: 2.5, // index: 1
0: 0.5, // index: 0
2: 1.5, // index: 2
}
fmt.Println(rates)
// above array literal equals to this:
//
// rates := [3]float64{
// 0.5,
// 2.5,
// 1.5,
// }
}
================================================
FILE: 14-arrays/11-keyed-elements/04-keyed-auto-initialize/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
rates := [3]float64{
// index 0 empty
// index 1 empty
2: 1.5, // index: 2
}
fmt.Println(rates)
// above array literal equals to this:
//
// rates := [3]float64{
// 0.,
// 0.,
// 1.5,
// }
}
================================================
FILE: 14-arrays/11-keyed-elements/05-keyed-auto-initialize-ellipsis/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// below ellipsis (...) calculates the length of the
// array automatically
rates := [...]float64{
// index 0 empty
// index 1 empty
// index 2 empty
// index 3 empty
// index 4 empty
5: 1.5, // index: 5
}
fmt.Println(rates)
// above array literal equals to this:
//
// rates := [6]float64{
// 0.,
// 0.,
// 0.,
// 0.,
// 0.,
// 1.5,
// }
}
================================================
FILE: 14-arrays/11-keyed-elements/06-keyed-and-unkeyed/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
rates := [...]float64{
// index 1 to 4 empty
5: 1.5, // index: 5
2.5, // index: 6
0: 0.5, // index: 0
}
fmt.Println(rates)
// above array literal equals to this:
//
// rates := [7]float64{
// 0.5,
// 0.,
// 0.,
// 0.,
// 0.,
// 1.5,
// 2.5,
// }
}
================================================
FILE: 14-arrays/11-keyed-elements/07-xratio-example/01-without-keys/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
rates := [...]float64{
25.5, // ethereum
120.5, // wanchain
}
// uses magic values - not good
fmt.Printf("1 BTC is %g ETH\n", rates[0])
fmt.Printf("1 BTC is %g WAN\n", rates[1])
}
================================================
FILE: 14-arrays/11-keyed-elements/07-xratio-example/02-with-keys/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// REFACTORED VERSION
// It uses well-defined names instead of magic numbers.
// Thanks to the keyed elements and constants.
func main() {
const (
ETH = 9 - iota
WAN
ICX
// you can add more cryptocurrencies here
// watch out the -1 index though!
)
rates := [...]float64{
ETH: 25.5,
WAN: 120.5,
ICX: 20,
// you can add more cryptocurrencies here
}
// uses well-defined names (ETH, WAN, ...) - good
fmt.Printf("1 BTC is %g ETH\n", rates[ETH])
fmt.Printf("1 BTC is %g WAN\n", rates[WAN])
fmt.Printf("1 BTC is %g ICX\n", rates[ICX])
fmt.Printf("%#v\n", rates)
}
================================================
FILE: 14-arrays/12-compare-unnamed/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// STORY:
// You want to compare two bookcases,
// whether they're equal or not.
func main() {
type (
// integer int
bookcase [5]int
cabinet [5]int
// ^- try changing this to: integer
// but first: uncomment the integer type above
)
blue := bookcase{6, 9, 3, 2, 1}
red := cabinet{6, 9, 3, 2, 1}
fmt.Print("Are they equal? ")
if cabinet(blue) == red {
fmt.Println("✅")
} else {
fmt.Println("❌")
}
fmt.Printf("blue: %#v\n", blue)
fmt.Printf("red : %#v\n", bookcase(red))
// ------------------------------------------------
// The underlying type of an unnamed type is itself.
//
// [5]integer's underlying type: [5]integer
// [5]int's underlying type : [5]int
//
// > [5]integer and [5]int are different types.
// > Their memory layout is not important.
// > Their types are not the same.
// _ = [5]integer{} == [5]int{}
// ------------------------------------------------
// An unnamed and a named type can be compared,
// if they've identical underlying types.
//
// [5]integer's underlying type: [5]integer
// cabinet's underlying type : [5]integer
//
// Note: Assuming the cabinet's type definition is like so:
// type cabinet [5]integer
// _ = [5]integer{} == cabinet{}
}
================================================
FILE: 14-arrays/exercises/01-declare-empty/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Declare empty arrays
//
// 1. Declare and print the following arrays with their types:
//
// 1. The names of your three best friends (names array)
//
// 2. The distances to five different locations (distances array)
//
// 3. A data buffer with five bytes of capacity (data array)
//
// 4. Currency exchange ratios only for a single currency (ratios array)
//
// 5. Up/Down status of four different web servers (alives array)
//
// 6. A byte array that doesn't occupy memory space (zero array)
//
// 2. Print only the types of the same arrays.
//
// 3. Print only the elements of the same arrays.
//
// HINT
// When printing the elements of an array, you can use the usual Printf verbs.
//
// For example:
// When printing a string array, you can use "%q" verb as usual.
//
// EXPECTED OUTPUT
// names : [3]string{"", "", ""}
// distances: [5]int{0, 0, 0, 0, 0}
// data : [5]uint8{0x0, 0x0, 0x0, 0x0, 0x0}
// ratios : [1]float64{0}
// alives : [4]bool{false, false, false, false}
// zero : [0]uint8{}
//
// names : [3]string
// distances: [5]int
// data : [5]uint8
// ratios : [1]float64
// alives : [4]bool
// zero : [0]uint8
//
// names : ["" "" ""]
// distances: [0 0 0 0 0]
// data : [0 0 0 0 0]
// ratios : [0.00]
// alives : [false false false false]
// zero : []
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/exercises/01-declare-empty/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
names [3]string // The names of your three best friends
distances [5]int // The distances to five different locations
data [5]byte // A data buffer with five bytes of capacity
ratios [1]float64 // Currency exchange ratios only for a single currency
alives [4]bool // Up/Down status of four different web servers
zero [0]byte // A byte array that doesn't occupy memory space
)
// 1. Declare and print the arrays with their types.
fmt.Printf("names : %#v\n", names)
fmt.Printf("distances: %#v\n", distances)
fmt.Printf("data : %#v\n", data)
fmt.Printf("ratios : %#v\n", ratios)
fmt.Printf("alives : %#v\n", alives)
fmt.Printf("zero : %#v\n", zero)
// 2. Print only the types of the same arrays.
fmt.Println()
fmt.Printf("names : %T\n", names)
fmt.Printf("distances: %T\n", distances)
fmt.Printf("data : %T\n", data)
fmt.Printf("ratios : %T\n", ratios)
fmt.Printf("alives : %T\n", alives)
fmt.Printf("zero : %T\n", zero)
// 3. Print only the elements of the same arrays.
fmt.Println()
fmt.Printf("names : %q\n", names)
fmt.Printf("distances: %d\n", distances)
fmt.Printf("data : %d\n", data)
fmt.Printf("ratios : %.2f\n", ratios)
fmt.Printf("alives : %t\n", alives)
fmt.Printf("zero : %d\n", zero)
}
================================================
FILE: 14-arrays/exercises/02-get-set-arrays/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Get and Set Array Elements
//
// 1. Use the 01-declare-empty exercise
// 2. Remove everything but the array declarations
//
// 3. Assign your best friends' names to the names array
//
// 4. Assign distances to the closest cities to you to the distance array
//
// 5. Assign arbitrary bytes to the data array
//
// 6. Assign a value to the ratios array
//
// 7. Assign true/false values to the alives arrays
//
// 8. Try to assign to the zero array and observe the error
//
// 9. Now use ordinary loop statements for each array and print them
// (do not use for range)
//
// 10. Now use for range loop statements for each array and print them
//
// 11. Try assigning different types of values to the arrays, break things,
// and observe the errors
//
// 12. Remove some of the array assignments and observe the loop outputs
// (zero values)
//
//
// EXPECTED OUTPUT
//
// Note: The output can change depending on the values that you've assigned to them, of course.
// You're free to assign any values.
//
// names
// ====================
// names[0]: "Einstein"
// names[1]: "Tesla"
// names[2]: "Shepard"
//
// distances
// ====================
// distances[0]: 50
// distances[1]: 40
// distances[2]: 75
// distances[3]: 30
// distances[4]: 125
//
// data
// ====================
// data[0]: 72
// data[1]: 69
// data[2]: 76
// data[3]: 76
// data[4]: 79
//
// ratios
// ====================
// ratios[0]: 3.14
//
// alives
// ====================
// alives[0]: true
// alives[1]: false
// alives[2]: true
// alives[3]: false
//
// zero
// ====================
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// FOR RANGES
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// names
// ====================
// names[0]: "Einstein"
// names[1]: "Tesla"
// names[2]: "Shepard"
//
// distances
// ====================
// distances[0]: 50
// distances[1]: 40
// distances[2]: 75
// distances[3]: 30
// distances[4]: 125
//
// data
// ====================
// data[0]: 72
// data[1]: 69
// data[2]: 76
// data[3]: 76
// data[4]: 79
//
// ratios
// ====================
// ratios[0]: 3.14
//
// alives
// ====================
// alives[0]: true
// alives[1]: false
// alives[2]: true
// alives[3]: false
//
// zero
// ====================
//
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/exercises/02-get-set-arrays/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
var (
names [3]string // The names of your three best friends
distances [5]int // The distances to five different locations
data [5]byte // A data buffer with five bytes of capacity
ratios [1]float64 // Currency exchange ratios only for a single currency
alives [4]bool // Up/Down status of four different web servers
zero [0]byte // A byte array that doesn't occupy memory space
)
names[0] = "Einstein"
names[1] = "Tesla"
names[2] = "Shepard"
distances[0] = 50
distances[1] = 40
distances[2] = 75
distances[3] = 30
distances[4] = 125
data[0] = 'H'
data[1] = 'E'
data[2] = 'L'
data[3] = 'L'
data[4] = 'O'
ratios[0] = 3.14145
alives[0] = true
alives[1] = false
alives[2] = true
alives[3] = false
// zero[0] = "BOMB!"
_ = zero
// =========================================================================
separator := "\n" + strings.Repeat("=", 20) + "\n"
fmt.Print("names", separator)
for i := 0; i < len(names); i++ {
fmt.Printf("names[%d]: %q\n", i, names[i])
}
fmt.Print("\ndistances", separator)
for i := 0; i < len(distances); i++ {
fmt.Printf("distances[%d]: %d\n", i, distances[i])
}
fmt.Print("\ndata", separator)
for i := 0; i < len(data); i++ {
// try the %c verb
fmt.Printf("data[%d]: %d\n", i, data[i])
}
fmt.Print("\nratios", separator)
for i := 0; i < len(ratios); i++ {
fmt.Printf("ratios[%d]: %.2f\n", i, ratios[i])
}
fmt.Print("\nalives", separator)
for i := 0; i < len(alives); i++ {
fmt.Printf("alives[%d]: %t\n", i, alives[i])
}
// no loop for zero elements
fmt.Print("\nzero", separator)
for i := 0; i < len(zero); i++ {
fmt.Printf("zero[%d]: %d\n", i, zero[i])
}
// =========================================================================
// you know how this works :) don't be freaked out!
fmt.Printf(`
%s
FOR RANGES
%[1]s
`, strings.Repeat("~", 30))
fmt.Print("names", separator)
for i, v := range names {
fmt.Printf("names[%d]: %q\n", i, v)
}
fmt.Print("\ndistances", separator)
for i, v := range distances {
fmt.Printf("distances[%d]: %d\n", i, v)
}
fmt.Print("\ndata", separator)
for i, v := range data {
// try the %c verb
fmt.Printf("data[%d]: %d\n", i, v)
}
fmt.Print("\nratios", separator)
for i, v := range ratios {
fmt.Printf("ratios[%d]: %.2f\n", i, v)
}
fmt.Print("\nalives", separator)
for i, v := range alives {
fmt.Printf("alives[%d]: %t\n", i, v)
}
// no loop for zero elements
fmt.Print("\nzero", separator)
for i, v := range zero {
fmt.Printf("zero[%d]: %d\n", i, v)
}
}
================================================
FILE: 14-arrays/exercises/03-array-literal/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Refactor to Array Literals
//
// 1. Use the 02-get-set-arrays exercise
//
// 2. Refactor the array assignments to array literals
//
// 1. You would need to change the array declarations to array literals
//
// 2. Then, you would need to move the right-hand side of the assignments,
// into the array literals.
//
// EXPECTED OUTPUT
// The output should be the same as the 02-get-set-arrays exercise.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/exercises/03-array-literal/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
// The names of your three best friends
names := [3]string{
"Einstein",
"Tesla",
"Shepard",
}
// The distances to five different locations
distances := [5]int{50, 40, 75, 30, 125}
// A data buffer with five bytes of capacity
data := [5]byte{'H', 'E', 'L', 'L', 'O'}
// Currency exchange ratios only for a single currency
ratios := [1]float64{3.14145}
// Up/Down status of four different web servers
alives := [4]bool{true, false, true, false}
// A byte array that doesn't occupy memory space
//
// Don't do this:
// zero := [0]byte{}
//
// Do this (when you don't assign elements):
var zero [0]byte
// =========================================================================
separator := "\n" + strings.Repeat("=", 20) + "\n"
fmt.Print("names", separator)
for i := 0; i < len(names); i++ {
fmt.Printf("names[%d]: %q\n", i, names[i])
}
fmt.Print("\ndistances", separator)
for i := 0; i < len(distances); i++ {
fmt.Printf("distances[%d]: %d\n", i, distances[i])
}
fmt.Print("\ndata", separator)
for i := 0; i < len(data); i++ {
// try the %c verb
fmt.Printf("data[%d]: %d\n", i, data[i])
}
fmt.Print("\nratios", separator)
for i := 0; i < len(ratios); i++ {
fmt.Printf("ratios[%d]: %.2f\n", i, ratios[i])
}
fmt.Print("\nalives", separator)
for i := 0; i < len(alives); i++ {
fmt.Printf("alives[%d]: %t\n", i, alives[i])
}
// no loop for zero elements
fmt.Print("\nzero", separator)
for i := 0; i < len(zero); i++ {
fmt.Printf("zero[%d]: %d\n", i, zero[i])
}
// =========================================================================
// you know how this works :) don't be freaked out!
fmt.Printf(`
%s
FOR RANGES
%[1]s
`, strings.Repeat("~", 30))
fmt.Print("names", separator)
for i, v := range names {
fmt.Printf("names[%d]: %q\n", i, v)
}
fmt.Print("\ndistances", separator)
for i, v := range distances {
fmt.Printf("distances[%d]: %d\n", i, v)
}
fmt.Print("\ndata", separator)
for i, v := range data {
// try the %c verb
fmt.Printf("data[%d]: %d\n", i, v)
}
fmt.Print("\nratios", separator)
for i, v := range ratios {
fmt.Printf("ratios[%d]: %.2f\n", i, v)
}
fmt.Print("\nalives", separator)
for i, v := range alives {
fmt.Printf("alives[%d]: %t\n", i, v)
}
// no loop for zero elements
fmt.Print("\nzero", separator)
for i, v := range zero {
fmt.Printf("zero[%d]: %d\n", i, v)
}
}
================================================
FILE: 14-arrays/exercises/04-ellipsis/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Refactor to Ellipsis
//
// 1. Use the 03-array-literal exercise
//
// 2. Refactor the length of the array literals to ellipsis
//
// This means: Use the ellipsis instead of defining the array's length
// manually.
//
// EXPECTED OUTPUT
// The output should be the same as the 03-array-literal exercise.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/exercises/04-ellipsis/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
// The names of your three best friends
names := [...]string{
"Einstein",
"Tesla",
"Shepard",
}
// The distances to five different locations
distances := [...]int{50, 40, 75, 30, 125}
// A data buffer with five bytes of capacity
data := [...]byte{'H', 'E', 'L', 'L', 'O'}
// Currency exchange ratios only for a single currency
ratios := [...]float64{3.14145}
// Up/Down status of four different web servers
alives := [...]bool{true, false, true, false}
// A byte array that doesn't occupy memory space
// Obviously, do not use ellipsis on this one
var zero []byte
// =========================================================================
separator := "\n" + strings.Repeat("=", 20) + "\n"
fmt.Print("names", separator)
for i := 0; i < len(names); i++ {
fmt.Printf("names[%d]: %q\n", i, names[i])
}
fmt.Print("\ndistances", separator)
for i := 0; i < len(distances); i++ {
fmt.Printf("distances[%d]: %d\n", i, distances[i])
}
fmt.Print("\ndata", separator)
for i := 0; i < len(data); i++ {
// try the %c verb
fmt.Printf("data[%d]: %d\n", i, data[i])
}
fmt.Print("\nratios", separator)
for i := 0; i < len(ratios); i++ {
fmt.Printf("ratios[%d]: %.2f\n", i, ratios[i])
}
fmt.Print("\nalives", separator)
for i := 0; i < len(alives); i++ {
fmt.Printf("alives[%d]: %t\n", i, alives[i])
}
// no loop for zero elements
fmt.Print("\nzero", separator)
for i := 0; i < len(zero); i++ {
fmt.Printf("zero[%d]: %d\n", i, zero[i])
}
// =========================================================================
// you know how this works :) don't be freaked out!
fmt.Printf(`
%s
FOR RANGES
%[1]s
`, strings.Repeat("~", 30))
fmt.Print("names", separator)
for i, v := range names {
fmt.Printf("names[%d]: %q\n", i, v)
}
fmt.Print("\ndistances", separator)
for i, v := range distances {
fmt.Printf("distances[%d]: %d\n", i, v)
}
fmt.Print("\ndata", separator)
for i, v := range data {
// try the %c verb
fmt.Printf("data[%d]: %d\n", i, v)
}
fmt.Print("\nratios", separator)
for i, v := range ratios {
fmt.Printf("ratios[%d]: %.2f\n", i, v)
}
fmt.Print("\nalives", separator)
for i, v := range alives {
fmt.Printf("alives[%d]: %t\n", i, v)
}
// no loop for zero elements
fmt.Print("\nzero", separator)
for i, v := range zero {
fmt.Printf("zero[%d]: %d\n", i, v)
}
}
================================================
FILE: 14-arrays/exercises/05-fix/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Fix
//
// 1. Uncomment the code
//
// 2. And fix the problems
//
// 3. BONUS: Simplify the code
// ---------------------------------------------------------
func main() {
// var names [3]string = [3]string{
// "Einstein" "Shepard"
// "Tesla"
// }
// var books [5]string = [5]string{
// "Kafka's Revenge",
// "Stay Golden",
// "",
// "",
// ""
// }
// fmt.Printf("%q\n", names)
// fmt.Printf("%q\n", books)
}
================================================
FILE: 14-arrays/exercises/05-fix/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
names := [...]string{"Einstein", "Shepard", "Tesla"}
books := [5]string{"Kafka's Revenge", "Stay Golden"}
fmt.Printf("%q\n", names)
fmt.Printf("%q\n", books)
}
================================================
FILE: 14-arrays/exercises/06-compare/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Compare the Arrays
//
// 1. Uncomment the code
//
// 2. Fix the problems so that arrays become comparable
//
// EXPECTED OUTPUT
// true
// true
// false
// ---------------------------------------------------------
func main() {
// week := [...]string{"Monday", "Tuesday"}
// wend := [4]string{"Saturday", "Sunday"}
// fmt.Println(week != wend)
// evens := [...]int{2, 4, 6, 8, 10}
// evens2 := [...]int32{2, 4, 6, 8, 10}
// fmt.Println(evens == evens2)
// Use : uint8 for one of the arrays instead of byte here.
// Remember: Aliased types are the same types.
image := [5]byte{'h', 'i'}
var data [5]byte
fmt.Println(data == image)
}
================================================
FILE: 14-arrays/exercises/06-compare/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
week := [...]string{"Monday", "Tuesday"}
wend := [...]string{"Saturday", "Sunday"}
fmt.Println(week != wend)
evens := [...]int{2, 4, 6, 8, 10}
evens2 := [...]int{2, 4, 6, 8, 10}
fmt.Println(evens == evens2)
// Use : uint8 for one of the arrays instead of byte here.
// Remember: Aliased types are the same types.
image := [5]uint8{'h', 'i'}
var data [5]byte
fmt.Println(data == image)
}
================================================
FILE: 14-arrays/exercises/07-assign/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Assign the Arrays
//
// 1. Create an array named books
//
// 2. Add book titles to the array
//
// 3. Create two more copies of the array named: upper and lower
//
// 4. Change the book titles to uppercase in the upper array only
//
// 5. Change the book titles to lowercase in the lower array only
//
// 6. Print all the arrays
//
// 7. Observe that the arrays are not connected when they're copied.
//
// NOTE
// Check out the strings package, it has functions to convert letters to
// upper and lower cases.
//
// BONUS
// Invent your own arrays with different types other than string,
// and do some manipulations on them.
//
// EXPECTED OUTPUT
// Note: Don't worry about the book titles here, you can use any title.
//
// books: ["Kafka's Revenge" "Stay Golden" "Everythingship"]
// upper: ["KAFKA'S REVENGE" "STAY GOLDEN" "EVERYTHINGSHIP"]
// lower: ["kafka's revenge" "stay golden" "everythingship"]
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/exercises/07-assign/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
books := [...]string{"Kafka's Revenge", "Stay Golden", "Everythingship"}
upper, lower := books, books
for i := range books {
upper[i] = strings.ToUpper(upper[i])
lower[i] = strings.ToLower(lower[i])
}
fmt.Printf("books: %q\n", books)
fmt.Printf("upper: %q\n", upper)
fmt.Printf("lower: %q\n", lower)
}
================================================
FILE: 14-arrays/exercises/08-wizard-printer/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Wizard Printer
//
// In this exercise, your goal is to display a few famous scientists
// in a pretty table.
//
// 1. Create a multi-dimensional array
// 2. In each inner array, store the scientist's name, lastname and his/her
// nickname
// 3. Print their information in a pretty table using a loop.
//
// EXPECTED OUTPUT
// First Name Last Name Nickname
// ==================================================
// Albert Einstein time
// Isaac Newton apple
// Stephen Hawking blackhole
// Marie Curie radium
// Charles Darwin fittest
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/exercises/08-wizard-printer/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
names := [...][3]string{
{"First Name", "Last Name", "Nickname"},
{"Albert", "Einstein", "emc2"},
{"Isaac", "Newton", "apple"},
{"Stephen", "Hawking", "blackhole"},
{"Marie", "Curie", "radium"},
{"Charles", "Darwin", "fittest"},
}
for i := range names {
n := names[i]
fmt.Printf("%-15s %-15s %-15s\n", n[0], n[1], n[2])
if i == 0 {
fmt.Println(strings.Repeat("=", 50))
}
}
}
================================================
FILE: 14-arrays/exercises/09-currency-converter/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Currency Converter
//
// In this exercise, you're going to display currency exchange ratios
// against USD.
//
// 1. Declare a few constants with iota. They're going to be the keys
// of the array.
//
// 2. Create an array that contains the conversion ratios.
//
// You should use keyed elements and the contants you've declared before.
//
// 3. Get the USD amount to be converted from the command line.
//
// 4. Handle the error cases for missing or invalid input.
//
// 5. Print the exchange ratios.
//
// EXPECTED OUTPUT
// go run main.go
// Please provide the amount to be converted.
//
// go run main.go invalid
// Invalid amount. It should be a number.
//
// go run main.go 10.5
// 10.50 USD is 9.24 EUR
// 10.50 USD is 8.19 GBP
// 10.50 USD is 1186.71 JPY
//
// go run main.go 1
// 1.00 USD is 0.88 EUR
// 1.00 USD is 0.78 GBP
// 1.00 USD is 113.02 JPY
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/exercises/09-currency-converter/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
const (
EUR = iota
GBP
JPY
)
rates := [...]float64{
EUR: 0.88,
GBP: 0.78,
JPY: 113.02,
}
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("Please provide the amount to be converted.")
return
}
amount, err := strconv.ParseFloat(args[0], 64)
if err != nil {
fmt.Println("Invalid amount. It should be a number.")
return
}
fmt.Printf("%.2f USD is %.2f EUR\n", amount, rates[EUR]*amount)
fmt.Printf("%.2f USD is %.2f GBP\n", amount, rates[GBP]*amount)
fmt.Printf("%.2f USD is %.2f JPY\n", amount, rates[JPY]*amount)
}
================================================
FILE: 14-arrays/exercises/10-hipsters-love-search/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Hipster's Love Bookstore Search Engine
//
// Your goal is to allow people to search for books.
//
// 1. Create an array with the following book titles:
// Kafka's Revenge
// Stay Golden
// Everythingship
// Kafka's Revenge 2nd Edition
//
// 2. Get the search query from the command-line argument
//
// 3. Search for the books in the books array
//
// 4. When the program finds the book, print it.
// 5. Otherwise, print that the book doesn't exist.
//
// 6. Handle the errors.
//
// RESTRICTION:
// + The search should be case insensitive.
//
// EXPECTED OUTPUT
// go run main.go
// Tell me a book title
//
// go run main.go STAY
// Search Results:
// + Stay Golden
//
// go run main.go sTaY
// Search Results:
// + Stay Golden
//
// go run main.go "Kafka's Revenge"
// Search Results:
// + Kafka's Revenge
// + Kafka's Revenge 2nd Edition
//
// go run main.go void
// Search Results:
// We don't have the book: "void"
//
// HINTS:
// + To find out whether a string contains another string value, you can use the strings.Contains function.
// + To convert a string value to lowercase, you can use the strings.ToLower function.
// + Check out the strings package for more information.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/exercises/10-hipsters-love-search/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
func main() {
books := [4]string{
"Kafka's Revenge",
"Stay Golden",
"Everythingship",
"Kafka's Revenge 2nd Edition",
}
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("Tell me a book title")
return
}
query := strings.ToLower(args[0])
fmt.Println("Search Results:")
var found bool
for _, v := range books {
if strings.Contains(strings.ToLower(v), query) {
fmt.Println("+", v)
found = true
}
}
if !found {
fmt.Printf("We don't have the book: %q\n", query)
}
}
================================================
FILE: 14-arrays/exercises/11-average/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Find the Average
//
// Your goal is to fill an array with numbers and find the average.
//
// 1. Get the numbers from the command-line.
//
// 2. Create an array and assign the given numbers to that array.
//
// 3. Print the given numbers and their average.
//
// RESTRICTION
// + Maximum 5 numbers can be provided
// + If one of the arguments are not a valid number, skip it
//
// EXPECTED OUTPUT
// go run main.go
// Please tell me numbers (maximum 5 numbers).
//
// go run main.go 1 2 3 4 5 6
// Please tell me numbers (maximum 5 numbers).
//
// go run main.go 1 2 3 4 5
// Your numbers: [1 2 3 4 5]
// Average: 3
//
// go run main.go 1 a 2 b 3
// Your numbers: [1 0 2 0 3]
// Average: 2
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/exercises/11-average/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
args := os.Args[1:]
if l := len(args); l == 0 || l > 5 {
fmt.Println("Please tell me numbers (maximum 5 numbers).")
return
}
var (
sum float64
nums [5]float64
total float64
)
for i, v := range args {
n, err := strconv.ParseFloat(v, 64)
if err != nil {
continue
}
total++
nums[i] = n
sum += n
}
fmt.Println("Your numbers:", nums)
fmt.Println("Average:", sum/total)
}
================================================
FILE: 14-arrays/exercises/12-sorter/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Number Sorter
//
// Your goal is to sort the given numbers from the command-line.
//
// 1. Get the numbers from the command-line.
//
// 2. Create an array and assign the given numbers to that array.
//
// 3. Sort the given numbers and print them.
//
// RESTRICTION
// + Maximum 5 numbers can be provided
// + If one of the arguments is not a valid number, skip it
//
// HINTS
// + You can use the bubble-sort algorithm to sort the numbers.
// Please watch this: https://youtu.be/nmhjrI-aW5o?t=7
//
// + When swapping the elements, do not check for the last element.
//
// Or, you will receive this error:
// "panic: runtime error: index out of range"
//
// EXPECTED OUTPUT
// go run main.go
// Please give me up to 5 numbers.
//
// go run main.go 6 5 4 3 2 1
// Sorry. Go arrays are fixed. So, for now, I'm only supporting sorting 5 numbers...
//
// go run main.go 5 4 3 2 1
// [1 2 3 4 5]
//
// go run main.go 5 4 a c 1
// [0 0 1 4 5]
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 14-arrays/exercises/12-sorter/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
args := os.Args[1:]
switch l := len(args); {
case l == 0:
fmt.Println("Please give me up to 5 numbers.")
return
case l > 5:
fmt.Println("Sorry. Go arrays are fixed.",
"So, for now, I'm only supporting sorting 5 numbers...")
return
}
var nums [5]float64
// fill the array with the numbers
for i, v := range args {
n, err := strconv.ParseFloat(v, 64)
if err != nil {
// skip if it's not a valid number
continue
}
nums[i] = n
}
/*
check whether it's the last element or not:
i < len(nums)-1
check whether the next number is greater than the current one, if so, swap it:
v > nums[i+1]
*/
for range nums {
for i, v := range nums {
if i < len(nums)-1 && v > nums[i+1] {
nums[i], nums[i+1] = nums[i+1], nums[i]
}
}
}
fmt.Println(nums)
}
================================================
FILE: 14-arrays/exercises/13-word-finder/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Word Finder
//
// Your goal is to search for the words inside the corpus.
//
// Note: This exercise is similar to the previous word finder program:
// https://github.com/inancgumus/learngo/tree/master/13-loops/10-word-finder-labeled-switch
//
// 1. Get the search query from the command-line (it can be multiple words)
//
// 2. Filter these words, do not search for them:
// and, or, was, the, since, very
//
// To do this, use an array for the filtered words.
//
// 3. Print the words found.
//
// RESTRICTION
// + The search and the filtering should be case insensitive
//
// HINT
// + strings.Fields function converts a given string to a slice.
//
// You can find its example in the word finder program that I've mentioned
// above.
//
// EXPECTED OUTPUT
// go run main.go
// Please give me a word to search.
//
// go run main.go and was
//
// go run main.go AND WAS
//
// go run main.go cat beginning
// #2 : "cat"
// #11: "beginning"
//
// go run main.go Cat Beginning
// #2 : "cat"
// #11: "beginning"
// ---------------------------------------------------------
const corpus = "lazy cat jumps again and again and again since the beginning this was very important"
func main() {
}
================================================
FILE: 14-arrays/exercises/13-word-finder/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
const corpus = "lazy cat jumps again and again and again since the beginning this was very important"
func main() {
query := os.Args[1:]
if len(query) == 0 {
fmt.Println("Please give me a word to search.")
return
}
filter := [...]string{
"and", "or", "was", "the", "since", "very",
}
words := strings.Fields(corpus)
queries:
for _, q := range query {
q = strings.ToLower(q)
for _, v := range filter {
if q == v {
continue queries
}
}
for i, w := range words {
if q == w {
fmt.Printf("#%-2d: %q\n", i+1, w)
break
}
}
}
}
================================================
FILE: 14-arrays/exercises/README.md
================================================
# Array Exercises
## Exercises Level I - Basics
1. **[Declare Empty Arrays](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/01-declare-empty)**
2. **[Get and Set Array Elements](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/02-get-set-arrays)**
3. **[Refactor to Array Literals](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/03-array-literal)**
4. **[Refactor to Ellipsis](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/04-ellipsis)**
5. **[Fix](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/05-fix)**
6. **[Compare the Arrays](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/06-compare)**
7. **[Assign the Arrays](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/07-assign)**
---
## Exercises Level II
1. **[Wizard Printer](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/08-wizard-printer)**
2. **[Currency Converter](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/09-currency-converter)**
3. **[Hipster's Bookstore Search Engine](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/10-hipsters-love-search)**
4. **[Find the Average](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/11-average)**
5. **[Number Sorter](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/12-sorter)**
6. **[Word Finder](https://github.com/inancgumus/learngo/tree/master/14-arrays/exercises/13-word-finder)**
================================================
FILE: 14-arrays/questions/1-array-basics.md
================================================
# Array Basics Quiz
## What's an array?
1. Accelerated charged particle array gun from Star Wars
2. Collection of values with dynamic length and type
3. Collection of values with fixed length and type *CORRECT*
## Where is the 2nd variable below stored in memory?
```go
// Let's say that the first variable below is stored in this memory location: 20th
var (
first int32 = 100
second int32 = 150
)
```
1. 21
2. 22
3. 24
4. It can be stored anywhere *CORRECT*
> **4:** That's right. It can be anywhere. Because, unlike arrays, there isn't any guarantee that variables will be stored in contiguous memory locations.
## Where is the 3rd element of the nums array stored in memory?
```go
// Let's say: nums array is stored in this memory location: 500th
var nums [5]int64
```
1. 3
2. 2
3. 502
4. 503
5. 516 *CORRECT*
> **2:** Nope, that's the index of an element.
>
> **3, 4:** 500+index? You're getting closer.
>
> **5:** Perfect. Array elements are stored in contiguous memory locations. Here, the array's location is 500, and each element is 8 bytes (int64). So, 1st element is stored in: 500th, 2nd element: 508th, 3rd element: 516th, and so on. Formula for math lovers: 516 = 500 + 8 * (3 - 1). General formula: Starting position + The size of each element * (Element's index position - 1).
## How many values this variable stores?
**HINT:** _I'm asking about the variable not about the array inside the variable._
```go
var gophers [10]string
```
1. 0
2. 1 *CORRECT*
3. 2
4. 10
> **2:** That's right! A variable can only store one value. Here, it stores a single array value. However, through the variable, you can also access to individual string values inside the array value.
>
> **4:** That's the length of the array. It's not the number of values that the gophers variable stores.
## What's the length of this array?
```go
var gophers [5]int
```
1. 5 *CORRECT*
2. 1
3. 2
> **1:** That's right! It stores 5 int values.
>
## What's the length of this array?
```go
const length = 5 * 2
var gophers [length - 1]int
```
1. 10
2. 9 *CORRECT*
3. 1
> **2:** That's right! 5 * 2 - 1 is 9. You can use constant expressions while declaring the length of an array.
## What's the element type of this array?
```go
var luminosity [100]float32
```
1. [100]float32
2. luminosity
3. float32 *CORRECT*
## What's the type of this array?
```go
var luminosity [100]float32
```
1. [100]float32 *CORRECT*
2. luminosity
3. float32
> **1:** That's right. Array's type is consisting of its length and its element type together.
>
## What does this program print?
```go
package main
import "fmt"
func main() {
var names [3]string
names[len(names)-1] = "!"
names[1] = "think" + names[2]
names[0] = "Don't"
names[0] += " "
fmt.Println(names[0] + names[1] + names[2])
}
```
1. !think!Don't
2. Don't think!! *CORRECT*
3. This program is incorrect
> **2:** "Don't think!! Just do!". Explanation is here: https://play.golang.org/p/y_Tqwn_XRlg
>
## What does this program print?
_It's OK if you can't solve this question. This is a hard question. You may try it on Go Playground here: https://play.golang.org/p/o0o0UM7Ktyy_
```go
package main
import "fmt"
// This program sets the next element of the array,
// then it quits just before the last element.
func main() {
var sum [5]int
for i, v := range sum {
if i == len(sum) - 1 {
break
}
sum[i+1] = 10
fmt.Print(v, " ")
}
}
```
1. 0 0 0 0 *CORRECT*
2. 10 10 10 10
3. 0 10 10 10
> **1:** That's right! the for range clause copies the sum array. So, changing the elements of the sum array while inside of the loop won't effect the original sum array. However, if you try to print it right after the loop, you'll see that it has changed. Try printing it like so on Go Playground.
>
> **2:** That's not right. Because, the for range clause copies the sum array.
>
================================================
FILE: 14-arrays/questions/2-arrays.md
================================================
# Arrays Quiz
## What's the length of this array literal?
```go
gadgets := [...]string{"Mighty Mouse", "Amazing Keyboard", "Shiny Monitor"}
```
1. 0
2. 1
3. 2
4. 3 *CORRECT*
> **4:** Yes! There are 3 elements in the element list. So, Go sets the length of the array to 3.
>
## What's the type and length of this array literal?
```go
gadgets := [...]string{}
```
1. [0]string and 0 *CORRECT*
2. [0]string{} and 0
3. [1]string and 1
4. [1]string{} and 1
> **1:** Yes! There are no elements in the element list. So, Go sets the length of the array to 0.
>
## What does this program print?
```go
package main
import "fmt"
func main() {
gadgets := [3]string{"Confused Drone"}
fmt.Printf("%q\n", gadgets)
}
```
1. [3]string{"Confused Drone", "", ""}
2. [1]string{"Confused Drone"}
3. ["Confused Drone" "" ""] *CORRECT*
4. ["Confused Drone"]
> **1:** %q verb doesn't print the type of an array.
>
> **2, 4:** Array's length cannot change depending on the elements.
>
> **3:** Yes! Go sets the uninitialized elements to their zero values.
>
## Are these arrays comparable?
```go
gadgets := [3]string{"Confused Drone"}
gears := [...]string{"Confused Drone"}
fmt.Println(gadgets == gears)
```
1. Yes, because they have identical types and elements
2. No, because their types are different *CORRECT*
3. No, because their elements are different
> **2:** Yes! gadget's type is [3]string whereas gears's type is [1]string.
>
## What does this program print?
```go
gadgets := [3]string{"Confused Drone", "Broken Phone"}
gears := gadgets
gears[2] = "Shiny Mouse"
fmt.Printf("%q\n", gadgets)
```
1. ["Confused Drone" "Broken Phone" "Shiny Mouse"]
2. ["Confused Drone" "Broken Phone" ""] *CORRECT*
3. ["" "" "Shiny Mouse"]
4. ["" "" ""]
> **2:** Yes! When you assign an array, Go creates a copy of the original array. So, gadgets and gears arrays are not connected. Changing one of them won't effect the other one.
>
## What's the type of the digits array?
```go
digits := [...][5]string{
{
"## ",
" # ",
" # ",
" # ",
"###",
},
[5]string{
"###",
" #",
"###",
" #",
"###",
},
}
```
1. [...][5]string
2. [2][2]string
3. [2][5]string *CORRECT*
4. [5][5]string
> **3:** Awesome! There are two inner arrays, so the outer array's length becomes 2. Also note that, `[5]string` in front of the second element is unnecessary.
>
## What does this program print?
```go
rates := [...]float64{
5: 1.5,
2.5,
0: 0.5,
}
fmt.Printf("%#v\n", rates)
```
1. [7]float64{0.5, 0, 0, 0, 0, 1.5, 2.5} *CORRECT*
2. [7]float64{1.5, 2.5, 0.5, 0, 0, 0, 0}
3. [3]float64{1.5, 2.5, 0.5}
4. [3]float64{0.5, 2.5, 1.5}
> **1:** That's right! For the explanation check out the example in the course repository here: https://github.com/inancgumus/learngo/tree/master/14-arrays/11-keyed-elements/06-keyed-and-unkeyed
>
## Are these arrays equal?
```go
type three [3]int
nums := [3]int{1, 2, 3}
nums2 := three{1, 2, 3}
fmt.Println(nums == nums2)
```
**Note:** _To solve this question you need to watch the comparison and unnamed types lectures._
1. Yes, because they have identical underlying types and elements *CORRECT*
2. No, because their types are different
3. No, because their length is different
> **1:** Yes! They both have the same underlying types: [3]int
>
## Are these array variables equal?
```go
type (
threeA [3]int
threeB [3]int
)
nums := threeA{1, 2, 3}
nums2 := threeA(threeB{1, 2, 3})
fmt.Println(nums == nums2)
```
**Note:** _To solve this question you need to the watch comparison and unnamed types lectures._
1. Yes, because they have identical underlying types and elements *CORRECT*
2. No, because their types are different
3. No, because their length is different
> **1:** Yes! Actually, arrays have different types, so normally they're not comparable. However, when you convert `threeB{1, 2, 3}` array to `threeA` type, they become comparable.
>
================================================
FILE: 14-arrays/questions/README.md
================================================
# Array Quizzes
* [Array Basics](1-array-basics.md)
* [Arrays](2-arrays.md)
================================================
FILE: 15-project-retro-led-clock/01-printing-the-digits/README.md
================================================
# GOAL 1: Printing the Digits
## Challenge Steps
1. Define a new placeholder type
2. Create the digits from "zero" to "nine"
You can use these characters for the clock:
```
Digit character : █
Separator character : ░
```
1. Put them into the "digits" array
2. Print the digits side-by-side
1. Loop for all the lines in a digit
2. Print each digit line by line
3. Don't forget printing a space after each digit
4. Don't forget printing a newline after each line
EXAMPLE: Let's say you want to print 10.
```
██ ███ <--- Print a new line after printing a single line from
█ █ █ all the digits.
█ █ █
█ █ █
███ ███
^^
||
++----> Add space between the digits
```
## Solution
You can find the solution in the solution folder.
================================================
FILE: 15-project-retro-led-clock/01-printing-the-digits/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
}
================================================
FILE: 15-project-retro-led-clock/01-printing-the-digits/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
// for keeping things easy to read and type-safe
type placeholder [5]string
zero := placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
one := placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
two := placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
three := placeholder{
"███",
" █",
"███",
" █",
"███",
}
four := placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
five := placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
six := placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
seven := placeholder{
"███",
" █",
" █",
" █",
" █",
}
eight := placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
nine := placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
// This array's type is "like": [10][5]string
//
// However:
// + "placeholder" is not equal to [5]string in type-wise.
// + Because: "placeholder" is a defined type, which is different
// from [5]string type.
// + [5]string is an unnamed type.
// + placeholder is a named type.
// + The underlying type of [5]string and placeholder is the same:
// [5]string
digits := [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
// Explanation: digits[0]
// + Each element of clock has the same length.
// + So: Getting the length of only one element is OK.
// + This could be: "zero" or "one" and so on... Instead of: digits[0]
//
// The range clause below is ~equal to the following code:
// line := 0; line < 5; line++
for line := range digits[0] {
// Print a line for each placeholder in digits
for digit := range digits {
fmt.Print(digits[digit][line], " ")
}
fmt.Println()
}
}
================================================
FILE: 15-project-retro-led-clock/02-printing-the-clock/README.md
================================================
# GOAL 2: Printing the Clock
## Notes
* Note main.go file contains the solution of the previous step.
* "solution" folder contains the solution for this step.
## Challenge Steps
1. Get the current time
2. Get the current hour, minute and second from the current time
3. Create the clock array by getting the digits from the digits array
4. Print the clock by using the clock array
5. Create a separator array (it's also a placeholder type)
6. Add the separators into the correct positions of the clock array
================================================
FILE: 15-project-retro-led-clock/02-printing-the-clock/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
type placeholder [5]string
zero := placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
one := placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
two := placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
three := placeholder{
"███",
" █",
"███",
" █",
"███",
}
four := placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
five := placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
six := placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
seven := placeholder{
"███",
" █",
" █",
" █",
" █",
}
eight := placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
nine := placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
digits := [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
for line := range digits[0] {
for digit := range digits {
fmt.Print(digits[digit][line], " ")
}
fmt.Println()
}
}
================================================
FILE: 15-project-retro-led-clock/02-printing-the-clock/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
type placeholder [5]string
zero := placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
one := placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
two := placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
three := placeholder{
"███",
" █",
"███",
" █",
"███",
}
four := placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
five := placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
six := placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
seven := placeholder{
"███",
" █",
" █",
" █",
" █",
}
eight := placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
nine := placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
colon := placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
digits := [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
fmt.Printf("hour: %d, min: %d, sec: %d\n", hour, min, sec)
// [8][5]string
clock := [...]placeholder{
// extract the digits: 17 becomes, 1 and 7 respectively
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
for digit := range clock {
fmt.Print(clock[digit][line], " ")
}
fmt.Println()
}
}
================================================
FILE: 15-project-retro-led-clock/03-animating-the-clock/README.md
================================================
# GOAL 3: Animate the Clock
## Notes
* Note main.go file contains the solution of the previous step.
* "solution" folder contains the solution for this step.
## Challenge Steps
1. Create an infinite loop to update the clock
2. Update the clock every second
[time.Sleep(time.Second)](https://golang.org/pkg/time/#Sleep) will stop the world for 1 second
3. Clear the screen before the infinite loop
1. Get my library for clearing the screen:
`go get -u github.com/inancgumus/screen`
2. Then, import it and call it in your code like this:
`screen.Clear()`
3. If you're using Go Playground instead, do this:
`fmt.Println("\f")`
4. Move the cursor to the top-left corner of the screen, before each step
of the infinite loop
* Call this in your code like this:
`screen.MoveTopLeft()`
* If you're using Go Playground instead, do this again:
`fmt.Println("\f")`
---
## SIDE NOTE FOR THE CURIOUS
If you're curious about how my screen clearing package works, read on.
**On bash**, it uses special commands, if you open the code, you can see that.
* `\033` is a special control code:
* `[2J` clears the screen and the cursor
* `[H` moves the cursor to 0, 0 screen position
* [See for more information](https://bluesock.org/~willkg/dev/ansi.html).
**On Windows**, I'm directly calling the Windows API functions. This is way advanced at this stage of the course, however, I'll probably explain it afterward.
So, my package automatically adjusts itself depending on where it is compiled. On Windows, it uses the special Windows API calls; On other operating systems, it uses the bash special commands that I've explained above.
================================================
FILE: 15-project-retro-led-clock/03-animating-the-clock/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
type placeholder [5]string
zero := placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
one := placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
two := placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
three := placeholder{
"███",
" █",
"███",
" █",
"███",
}
four := placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
five := placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
six := placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
seven := placeholder{
"███",
" █",
" █",
" █",
" █",
}
eight := placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
nine := placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
colon := placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
digits := [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
fmt.Printf("hour: %d, min: %d, sec: %d\n", hour, min, sec)
// [8][5]string
clock := [...]placeholder{
// extract the digits: 17 becomes, 1 and 7 respectively
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
for digit := range clock {
fmt.Print(clock[digit][line], " ")
}
fmt.Println()
}
}
================================================
FILE: 15-project-retro-led-clock/03-animating-the-clock/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
type placeholder [5]string
zero := placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
one := placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
two := placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
three := placeholder{
"███",
" █",
"███",
" █",
"███",
}
four := placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
five := placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
six := placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
seven := placeholder{
"███",
" █",
" █",
" █",
" █",
}
eight := placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
nine := placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
colon := placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
digits := [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
// For Go Playground, do not use this.
screen.Clear()
// Go Playground will not run an infinite loop.
// So, instead, you may loop for 1000 times:
// for i := 0; i < 1000; i++ {
for {
// For Go Playground, use this instead:
// fmt.Print("\f")
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
for digit := range clock {
fmt.Print(clock[digit][line], " ")
}
fmt.Println()
}
// pause for 1 second
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/04-blinking-the-separators/README.md
================================================
# GOAL 4: Blinking the Separators
## Notes
* Note main.go file contains the solution of the previous step.
* "solution" folder contains the solution for this step.
## Challenge Steps
Separators should be visible once in every two seconds.
### Example:
* 1st second: They're invisible
* 2nd second: visible
* 3rd second: invisible
* 4th second: visible
### HINT
There are two ways to do this:
1. Manipulating the clock array directly (by adding/removing the separators)
2. Or: Deciding what placeholders to print when printing the clock
================================================
FILE: 15-project-retro-led-clock/04-blinking-the-separators/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
type placeholder [5]string
zero := placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
one := placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
two := placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
three := placeholder{
"███",
" █",
"███",
" █",
"███",
}
four := placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
five := placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
six := placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
seven := placeholder{
"███",
" █",
" █",
" █",
" █",
}
eight := placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
nine := placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
colon := placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
digits := [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
screen.Clear()
for {
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
for digit := range clock {
fmt.Print(clock[digit][line], " ")
}
fmt.Println()
}
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/04-blinking-the-separators/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
type placeholder [5]string
zero := placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
one := placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
two := placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
three := placeholder{
"███",
" █",
"███",
" █",
"███",
}
four := placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
five := placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
six := placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
seven := placeholder{
"███",
" █",
" █",
" █",
" █",
}
eight := placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
nine := placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
colon := placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
digits := [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
screen.Clear()
for {
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
for index, digit := range clock {
// colon blink
next := clock[index][line]
if digit == colon && sec%2 == 0 {
next = " "
}
fmt.Print(next, " ")
}
fmt.Println()
}
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/05-full-annotated-solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
// for keeping things easy to read and type-safe
type placeholder [5]string
// put the digits (placeholders) into variables
// using the placeholder array type above
zero := placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
one := placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
two := placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
three := placeholder{
"███",
" █",
"███",
" █",
"███",
}
four := placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
five := placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
six := placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
seven := placeholder{
"███",
" █",
" █",
" █",
" █",
}
eight := placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
nine := placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
colon := placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
// This array's type is "like": [10][5]string
//
// However:
// + "placeholder" is not equal to [5]string in type-wise.
// + Because: "placeholder" is a defined type, which is different
// from [5]string type.
// + [5]string is an unnamed type.
// + placeholder is a named type.
// + The underlying type of [5]string and placeholder is the same:
// [5]string
digits := [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
// For Go Playground, do not use this.
screen.Clear()
// Go Playground will not run an infinite loop.
// Loop for example 1000 times instead, like this:
// for i := 0; i < 1000; i++ { ... }
for {
// For Go Playground, use this instead:
// fmt.Print("\f")
screen.MoveTopLeft()
// get the current hour, minute and second
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
// extract the digits: 17 becomes, 1 and 7 respectively
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
// Explanation: clock[0]
// + Each element of clock has the same length.
// + So: Getting the length of only one element is OK.
// + This could be: "zero" or "one" and so on... Instead of: digits[0]
//
// The range clause below is ~equal to the following code:
// line := 0; line < len(clock[0]); line++
for line := range clock[0] {
// Print a line for each placeholder in clock
for index, digit := range clock {
// Colon blink on every two seconds.
// + On each sec divisible by two, prints an empty line
// + Otherwise: prints the current pixel
next := clock[index][line]
if digit == colon && sec%2 == 0 {
next = " "
}
// Print the next line and,
// give it enough space for the next placeholder
fmt.Print(next, " ")
}
// After each line of a placeholder, print a newline
fmt.Println()
}
// pause for 1 second
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/README.md
================================================
## NOTES
- I've explained the challenges and the solutions step by step
- So, if you get stuck, you can check out the next step without having to look at the entire final solution
- You can find the explanations and solutions by clicking on the header links below
## GET SOCIAL
- Click the link below to tweet your solution when you complete: http://bit.ly/GOTWEET-CLOCK
- Discuss your solution with other gophers here: http://bit.ly/LEARNGOSLACK
---
## GOALS:
### 👉 [STEP #1 — Print the Digits](https://github.com/inancgumus/learngo/tree/master/15-project-retro-led-clock/01-printing-the-digits/)
- [ ] Define a new placeholder type
- [ ] Create the digit arrays from 0 to 9
- [ ] Put them into the "digits" array
- [ ] Print them side-by-side
### 👉 [STEP #2 — Print the Clock](https://github.com/inancgumus/learngo/tree/master/15-project-retro-led-clock/02-printing-the-clock/)
- [ ] Get the current time
- [ ] Create the clock array
- [ ] Print the clock
- [ ] Add the separators
### 👉 [STEP #3 — Animate the Clock](https://github.com/inancgumus/learngo/tree/master/15-project-retro-led-clock/03-animating-the-clock/)
- [ ] Create an infinite loop to update the clock
- [ ] Update the clock every second
- [ ] Clear the screen before the infinite loop
- [ ] Move the cursor to the top-left corner of the screen before each
step of the infinite loop
### 👉 [BONUS: STEP #4 — Blink the Clock](https://github.com/inancgumus/learngo/tree/master/15-project-retro-led-clock/04-blinking-the-separators/)
- [ ] Blink the separators
### 👉 [FULL ANNOTATED SOLUTION](https://github.com/inancgumus/learngo/tree/master/15-project-retro-led-clock/05-full-annotated-solution/main.go)
================================================
FILE: 15-project-retro-led-clock/exercises/01-refactor/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Refactor
//
// Goal is refactoring the clock project by moving some of its parts to
// a new file in the same package.
//
// 1. Create a new file: placeholders.go
// 2. Move the placeholder type to placeholder.go
// 3. Move all the placeholders (zero to nine and the colon) to placeholder.go
// 4. Move the digits array to placeholders.go
//
// HINT
// + placeholders.go file should belong to main package as well
//
// To remember how to do so: Rewatch the "PART I — Packages, Scopes and Importing"
// section.
//
// + Short declaration won't work in the package scope.
// Remember why by watching: "Short Declaration: Package Scope" lecture
//
// + If you receive the following error and you don't know what to do watch:
// "Packages - Learn how to run multiple files" lecture.
//
// # command-line-arguments
// undefined: placeholder
// undefined: colon
//
// EXPECTED OUTPUT
// The same output before the refactoring.
// ---------------------------------------------------------
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
type placeholder [5]string
zero := placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
one := placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
two := placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
three := placeholder{
"███",
" █",
"███",
" █",
"███",
}
four := placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
five := placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
six := placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
seven := placeholder{
"███",
" █",
" █",
" █",
" █",
}
eight := placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
nine := placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
colon := placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
digits := [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
screen.Clear()
for {
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
for index, digit := range clock {
// colon blink
next := clock[index][line]
if digit == colon && sec%2 == 0 {
next = " "
}
fmt.Print(next, " ")
}
fmt.Println()
}
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/exercises/01-refactor/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
screen.Clear()
for {
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
for index, digit := range clock {
// colon blink
next := clock[index][line]
if digit == colon && sec%2 == 0 {
next = " "
}
fmt.Print(next, " ")
}
fmt.Println()
}
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/exercises/01-refactor/solution/placeholders.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type placeholder [5]string
var zero = placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
var one = placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
var two = placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
var three = placeholder{
"███",
" █",
"███",
" █",
"███",
}
var four = placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
var five = placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
var six = placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
var seven = placeholder{
"███",
" █",
" █",
" █",
" █",
}
var eight = placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
var nine = placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
var colon = placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
var digits = [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
================================================
FILE: 15-project-retro-led-clock/exercises/02-alarm/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Set an Alarm
//
// Goal is printing " ALARM! " every 10 seconds.
//
// EXPECTED OUTPUT
//
// ██ ███ ███ ██ ███ ███
// █ █ ░ █ █ ░ █ █ █
// █ ███ ███ █ ███ ███
// █ █ ░ █ █ ░ █ █
// ███ ███ ███ ███ ███ ███
//
// ███ █ ███ ██ █ █ █
// █ █ █ █ █ █ █ ███ █
// ███ █ ███ ██ █ █ █
// █ █ █ █ █ █ █ █ █
// █ █ ███ █ █ █ █ █ █ █
//
// ██ ███ ███ ██ █ █ ██
// █ █ ░ █ █ ░ █ █ █
// █ ███ ███ █ ███ █
// █ █ ░ █ █ ░ █ █
// ███ ███ ███ ███ █ ███
//
// HINTS
//
// <<< BEWARE THE SPOILER! >>>
//
// I recommend you to first solve the exercise yourself before reading the
// following hint.
//
//
// + You can create a new array named alarm with the same length of the
// clocks array, so you can copy the alarm array to the clocks array
// every 10 seconds.
//
// ---------------------------------------------------------
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
screen.Clear()
for {
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
for index, digit := range clock {
// colon blink
next := clock[index][line]
if digit == colon && sec%2 == 0 {
next = " "
}
fmt.Print(next, " ")
}
fmt.Println()
}
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/exercises/02-alarm/placeholders.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type placeholder [5]string
var zero = placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
var one = placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
var two = placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
var three = placeholder{
"███",
" █",
"███",
" █",
"███",
}
var four = placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
var five = placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
var six = placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
var seven = placeholder{
"███",
" █",
" █",
" █",
" █",
}
var eight = placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
var nine = placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
var colon = placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
var digits = [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
================================================
FILE: 15-project-retro-led-clock/exercises/02-alarm/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
screen.Clear()
for {
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
alarmed := sec%10 == 0
for line := range clock[0] {
if alarmed {
clock = alarm
}
for index, digit := range clock {
next := clock[index][line]
if digit == colon && sec%2 == 0 {
next = " "
}
fmt.Print(next, " ")
}
fmt.Println()
}
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/exercises/02-alarm/solution/placeholders.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type placeholder [5]string
var zero = placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
var one = placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
var two = placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
var three = placeholder{
"███",
" █",
"███",
" █",
"███",
}
var four = placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
var five = placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
var six = placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
var seven = placeholder{
"███",
" █",
" █",
" █",
" █",
}
var eight = placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
var nine = placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
var colon = placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
var alarm = [...]placeholder{
{
" ",
" ",
" ",
" ",
" ",
},
{
"███",
"█ █",
"███",
"█ █",
"█ █",
},
{
"█ ",
"█ ",
"█ ",
"█ ",
"███",
},
{
"███",
"█ █",
"███",
"█ █",
"█ █",
},
{
"██ ",
"█ █",
"██ ",
"█ █",
"█ █",
},
{
"█ █",
"███",
"█ █",
"█ █",
"█ █",
},
{
" █ ",
" █ ",
" █ ",
" ",
" █ ",
},
{
" ",
" ",
" ",
" ",
" ",
},
}
var digits = [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
================================================
FILE: 15-project-retro-led-clock/exercises/03-split-second/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Add Split Seconds
//
// Your goal is adding the split second to the clock. A split second is
// 1/10th of a second.
//
// 1. Find the current split second
// 2. Add dot character to the clock (as in the expected output)
// 3. Add the split second digit to the clock
// 4. Blink the dot every two seconds (just like the separators)
// 5. Update the clock every 1/10th of a second, instead of every second.
// (Update the clock every 100 millliseconds)
//
// HINTS
// + You can find the split second using Nanosecond method of the Time type.
// https://golang.org/pkg/time/#Time.Nanosecond
//
// + A split second is the first digit of the Nanosecond.
//
// + Remember: time.Second is an integer constant, so it can be divided
// with a number.
//
// https://golang.org/pkg/time/#Time.Second
//
// EXPECTED OUTPUT
// Note that, clock is updated every split second instead of a second.
//
// Separators are displayed (second is an odd number):
//
// ██ ██ ███ ██ ██ ███ ███
// █ █ ░ █ █ ░ █ █ █ █
// █ █ ███ █ █ █ █ █
// █ █ ░ █ █ ░ █ █ █ █
// ███ ███ ███ ███ ███ █ ░ ███
//
// ██ ██ ███ ██ ██ ███ ██
// █ █ ░ █ █ ░ █ █ █
// █ █ ███ █ █ █ █
// █ █ ░ █ █ ░ █ █ █
// ███ ███ ███ ███ ███ █ ░ ███
//
// ██ ██ ███ ██ ██ ███ ███
// █ █ ░ █ █ ░ █ █ █
// █ █ ███ █ █ █ ███
// █ █ ░ █ █ ░ █ █ █
// ███ ███ ███ ███ ███ █ ░ ███
//
// ██ ██ ███ ██ ██ ███ ███
// █ █ ░ █ █ ░ █ █ █
// █ █ ███ █ █ █ ███
// █ █ ░ █ █ ░ █ █ █
// ███ ███ ███ ███ ███ █ ░ ███
//
// ██ ██ ███ ██ ██ ███ █ █
// █ █ ░ █ █ ░ █ █ █ █
// █ █ ███ █ █ █ ███
// █ █ ░ █ █ ░ █ █ █
// ███ ███ ███ ███ ███ █ ░ █
//
// ██ ██ ███ ██ ██ ███ ███
// █ █ ░ █ █ ░ █ █ █
// █ █ ███ █ █ █ ███
// █ █ ░ █ █ ░ █ █ █
// ███ ███ ███ ███ ███ █ ░ ███
//
// ██ ██ ███ ██ ██ ███ ███
// █ █ ░ █ █ ░ █ █ █
// █ █ ███ █ █ █ ███
// █ █ ░ █ █ ░ █ █ █ █
// ███ ███ ███ ███ ███ █ ░ ███
//
// ██ ██ ███ ██ ██ ███ ███
// █ █ ░ █ █ ░ █ █ █
// █ █ ███ █ █ █ █
// █ █ ░ █ █ ░ █ █ █
// ███ ███ ███ ███ ███ █ ░ █
//
// ██ ██ ███ ██ ██ ███ ███
// █ █ ░ █ █ ░ █ █ █ █
// █ █ ███ █ █ █ ███
// █ █ ░ █ █ ░ █ █ █ █
// ███ ███ ███ ███ ███ █ ░ ███
//
// ██ ██ ███ ██ ██ ███ ███
// █ █ ░ █ █ ░ █ █ █ █
// █ █ ███ █ █ █ ███
// █ █ ░ █ █ ░ █ █ █
// ███ ███ ███ ███ ███ █ ░ ███
//
// Separators are not displayed (second is an even number):
//
// ██ ██ ███ ██ ██ ███ ███
// █ █ █ █ █ █ █ █ █
// █ █ ███ █ █ ███ █ █
// █ █ █ █ █ █ █ █ █
// ███ ███ ███ ███ ███ ███ ███
//
// ---------------------------------------------------------
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
screen.Clear()
for {
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
for index, digit := range clock {
// colon blink
next := clock[index][line]
if digit == colon && sec%2 == 0 {
next = " "
}
fmt.Print(next, " ")
}
fmt.Println()
}
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/exercises/03-split-second/placeholders.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type placeholder [5]string
var zero = placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
var one = placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
var two = placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
var three = placeholder{
"███",
" █",
"███",
" █",
"███",
}
var four = placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
var five = placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
var six = placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
var seven = placeholder{
"███",
" █",
" █",
" █",
" █",
}
var eight = placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
var nine = placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
var colon = placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
var digits = [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
================================================
FILE: 15-project-retro-led-clock/exercises/03-split-second/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
screen.Clear()
for {
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
ssec := now.Nanosecond() / 1e8
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
dot,
digits[ssec],
}
for line := range clock[0] {
for index, digit := range clock {
next := clock[index][line]
if (digit == colon || digit == dot) && sec%2 == 0 {
next = " "
}
fmt.Print(next, " ")
}
fmt.Println()
}
const splitSecond = time.Second / 10
time.Sleep(splitSecond)
}
}
================================================
FILE: 15-project-retro-led-clock/exercises/03-split-second/solution/placeholders.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type placeholder [5]string
var zero = placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
var one = placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
var two = placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
var three = placeholder{
"███",
" █",
"███",
" █",
"███",
}
var four = placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
var five = placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
var six = placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
var seven = placeholder{
"███",
" █",
" █",
" █",
" █",
}
var eight = placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
var nine = placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
var colon = placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
var dot = placeholder{
" ",
" ",
" ",
" ",
" ░ ",
}
var digits = [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
================================================
FILE: 15-project-retro-led-clock/exercises/04-ticker/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Ticker: Slide the Clock
//
// Your goal is slide the placeholders every second.
// Please run the solution to see it in action.
//
//
// THIS IS A HARD EXERCISE:
// + It will take you days but it will be worth it.
// + For experienced developers, this can take an hour or so.
//
//
// 1. You need to determine the starting and the ending digits to create
// the sliding effect.
//
//
// 2. Each second, start from the next placeholder, skip the previous one.
// This means: Only draw the next placeholders.
//
// Like this:
//
// 12:40:31
// 2:40:31
// 40:31
// 0:31
// :31
// 31
// 1
//
//
// 3. After the last placeholder is displayed, fill the lines for the missing
// placeholders, and then start from the first placeholder. Draw it to the
// right part of the screen.
//
// Like this:
//
// 12:40:31
// 2:40:31
// 40:31
// 0:31
// :31
// 31
// 1
// 1
// 12
// 12:
// 12:4
// 12:40
// 12:40:
// 12:40:3
// 12:40:31
//
// As you can see, you need to draw the clock from the right part of the
// screen, beginning from the first placeholder.
//
//
// HINTS
// + You would need to clear the screen inside the loop instead of once.
// Otherwise the previous placeholders will be left on the screen.
//
//
// EXPECTED OUTPUT
// Please run the solution to see it in action. Do not look at the source-code
// though.
// ---------------------------------------------------------
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
screen.Clear()
for {
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
for index, digit := range clock {
next := clock[index][line]
if digit == colon && sec%2 == 0 {
next = " "
}
fmt.Print(next, " ")
}
fmt.Println()
}
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/exercises/04-ticker/placeholders.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type placeholder [5]string
var zero = placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
var one = placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
var two = placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
var three = placeholder{
"███",
" █",
"███",
" █",
"███",
}
var four = placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
var five = placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
var six = placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
var seven = placeholder{
"███",
" █",
" █",
" █",
" █",
}
var eight = placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
var nine = placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
var colon = placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
var digits = [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
================================================
FILE: 15-project-retro-led-clock/exercises/04-ticker/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
for shift := 0; ; shift++ {
// we need to clear the screen here.
// or the previous character will be left on the screen
//
// alternative: you can fill the rest of the missing placeholders
// with empty lines
screen.Clear()
screen.MoveTopLeft()
now := time.Now()
hour, min, sec := now.Hour(), now.Minute(), now.Second()
clock := [...]placeholder{
digits[hour/10], digits[hour%10],
colon,
digits[min/10], digits[min%10],
colon,
digits[sec/10], digits[sec%10],
}
for line := range clock[0] {
l := len(clock)
// this sets the beginning and the ending placeholder positions (indexes).
// shift%l prevents the indexing error.
s, e := shift%l, l
// to slide the placeholders from the right part of the screen.
//
// here, we assume that as if the clock's length is double of its length.
// this makes things easy to manage: that's why: l*2 is there.
//
// shift is always increasing, for it's to go beyond the clock's length,
// it should be equal or greater than l*2, right (after the remainder of course)?
//
// so, if the clock goes beyond its length; this code detects that,
// and resets the starting position to the first placeholder's index,
// and it keeps doing so until the clock is fully displayed again.
if shift%(l*2) >= l {
s, e = 0, s
}
// print empty lines for the missing place holders.
// this creates the effect of moving placeholders from right to left.
//
// l-e can only be non-zero when the above if statement runs.
// otherwise, l-e is always zero, because l == e.
//
// this is one of the other benefits of assuming the length of the
// clock as the double of its length. otherwise, l-e would always be 0.
for j := 0; j < l-e; j++ {
fmt.Print(" ")
}
// draw the digits starting from 's' to 'e'
for i := s; i < e; i++ {
next := clock[i][line]
if clock[i] == colon && sec%2 == 0 {
next = " "
}
fmt.Print(next, " ")
}
fmt.Println()
}
time.Sleep(time.Second)
}
}
================================================
FILE: 15-project-retro-led-clock/exercises/04-ticker/solution/placeholders.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type placeholder [5]string
var zero = placeholder{
"███",
"█ █",
"█ █",
"█ █",
"███",
}
var one = placeholder{
"██ ",
" █ ",
" █ ",
" █ ",
"███",
}
var two = placeholder{
"███",
" █",
"███",
"█ ",
"███",
}
var three = placeholder{
"███",
" █",
"███",
" █",
"███",
}
var four = placeholder{
"█ █",
"█ █",
"███",
" █",
" █",
}
var five = placeholder{
"███",
"█ ",
"███",
" █",
"███",
}
var six = placeholder{
"███",
"█ ",
"███",
"█ █",
"███",
}
var seven = placeholder{
"███",
" █",
" █",
" █",
" █",
}
var eight = placeholder{
"███",
"█ █",
"███",
"█ █",
"███",
}
var nine = placeholder{
"███",
"█ █",
"███",
" █",
"███",
}
var colon = placeholder{
" ",
" ░ ",
" ",
" ░ ",
" ",
}
var digits = [...]placeholder{
zero, one, two, three, four, five, six, seven, eight, nine,
}
================================================
FILE: 15-project-retro-led-clock/exercises/README.md
================================================
# Exercises
These exercises will reinforce your knowledge of manipulating arrays. You will prove yourself that you can write easy to maintain Go programs.
1. **[Refactor](https://github.com/inancgumus/learngo/tree/master/15-project-retro-led-clock/exercises/01-refactor)**
In this exercise, you will refactor the project to multiple files by moving
all the placeholders. This will make the project easy to maintain down the road.
2. **[Set an Alarm](https://github.com/inancgumus/learngo/tree/master/15-project-retro-led-clock/exercises/02-alarm)**
You will print " ALARM! " every 10 seconds.
3. **[Split Second](https://github.com/inancgumus/learngo/tree/master/15-project-retro-led-clock/exercises/03-split-second)**
You will display the split second in the clock, you will need to update the
clock every 1/10th of a second instead of every second.
4. **[Ticker](https://github.com/inancgumus/learngo/tree/master/15-project-retro-led-clock/exercises/04-ticker)**
This is a HARD EXERCISE. You will slide the clock animation from right-to-left. After this exercise, you will truly feel that you've mastered everything you've learned so far.
================================================
FILE: 16-slices/01-slices-vs-arrays/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
{
// its length is part of its type
var nums [5]int
fmt.Printf("nums array: %#v\n", nums)
}
{
// its length is not part of its type
var nums []int
fmt.Printf("nums slice: %#v\n", nums)
fmt.Printf("len(nums) : %d\n", len(nums))
// won't work: the slice is nil.
// fmt.Printf("nums[0]: %d\n", nums[0])
// fmt.Printf("nums[1]: %d\n", nums[1])
}
}
================================================
FILE: 16-slices/02-slices-vs-arrays/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var array [2]int
// zero value of an array is zero-valued elements
fmt.Printf("array : %#v\n", array)
// nope: arrays are fixed length
// array[2] = 0
var slice []int
// zero value of a slice is nil
fmt.Println("slice == nil?", slice == nil)
// nope: they don't exist:
// _ = slice[0]
// _ = slice[1]
// len function still works though
fmt.Println("len(slice) :", len(slice))
// array's length is part of its type
fmt.Printf("array's type: %T\n", array)
// whereas, slice's length isn't part of its type
fmt.Printf("slice's type: %T\n", slice)
}
================================================
FILE: 16-slices/03-slices-vs-arrays-examples/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// STORY:
// You want to list the books and games you have
func main() {
var books [5]string
books[0] = "dracula"
books[1] = "1984"
books[2] = "island"
newBooks := [5]string{"ulysses", "fire"}
if books == newBooks {
}
books = newBooks
games := []string{"pokemon", "sims"}
newGames := []string{"pacman", "doom", "pong"}
newGames = games
games = nil
games = []string{}
var ok string
for i, game := range games {
if game != newGames[i] {
ok = "not "
break
}
}
if len(games) != len(newGames) {
ok = "not "
}
fmt.Printf("games and newGames are %sequal\n\n", ok)
fmt.Printf("books : %#v\n", books)
fmt.Printf("new books : %#v\n", newBooks)
fmt.Printf("games : %T\n", games)
fmt.Printf("new games : %#v\n", newGames)
fmt.Printf("games's length: %d\n", len(games))
fmt.Printf("games's nil : %t\n", games == nil)
}
================================================
FILE: 16-slices/04-slices-vs-arrays-unique-nums/01-with-arrays/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
const max = 5
var uniques [max]int
// It's harder to make a program dynamic using arrays
// max, _ := strconv.Atoi(os.Args[1])
// var uniques [10]int
loop:
for found := 0; found < max; {
n := rand.Intn(max) + 1
fmt.Print(n, " ")
for _, u := range uniques {
if u == n {
continue loop
}
}
uniques[found] = n
found++
}
fmt.Println("\n\nuniques:", uniques)
}
================================================
FILE: 16-slices/04-slices-vs-arrays-unique-nums/02-with-slices/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"sort"
"strconv"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
max, _ := strconv.Atoi(os.Args[1])
// declare an uninitialized nil slice
var uniques []int
loop:
// you can still use the len function on a nil slice
for len(uniques) < max {
n := rand.Intn(max) + 1
fmt.Print(n, " ")
for _, u := range uniques {
if u == n {
continue loop
}
}
// append function can add new elements to a slice
uniques = append(uniques, n)
// a slice doesn't contain any elements right from the start
// uniques[found] = n
// found++
}
fmt.Println("\n\nuniques:", uniques)
fmt.Println("\nlength of uniques:", len(uniques))
sort.Ints(uniques)
fmt.Println("\nsorted:", uniques)
nums := [5]int{5, 4, 3, 2, 1}
sort.Ints(nums[:])
fmt.Println("\nnums:", nums)
}
================================================
FILE: 16-slices/05-append/1-theory/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
func main() {
nums := []int{1, 2, 3}
s.Show("nums", nums)
_ = append(nums, 4)
s.Show("nums", nums)
nums = append(nums, 4)
s.Show("nums", nums)
nums = append(nums, 9)
s.Show("nums", nums)
nums = append(nums, 4)
s.Show("nums", nums)
// or:
// nums = append(nums, 4, 9)
// s.Show("nums", nums)
nums = []int{1, 2, 3}
tens := []int{12, 13}
nums = append(nums, tens...)
s.Show("nums", nums)
}
================================================
FILE: 16-slices/05-append/2-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
func main() {
var todo []string
todo = append(todo, "sing")
// you can only append elements with the same element type of the slice
// todo = append(todo, 42)
todo = append(todo, "run")
// append is a variadic function, so you can append multiple elements
todo = append(todo, "code", "play")
// you can also append a slice to another slice using ellipsis: ...
tomorrow := []string{"see mom", "learn go"}
todo = append(todo, tomorrow...)
// todo = append(todo, "see mom", "learn go")
s.Show("todo", todo)
}
================================================
FILE: 16-slices/06-slice-expressions/1-theory/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
func main() {
msg := []byte{'h', 'e', 'l', 'l', 'o'}
s.Show("msg", msg)
s.Show("msg[0:1]", msg[0:1])
s.Show("msg[0:2]", msg[0:2])
s.Show("msg[0:3]", msg[0:3])
s.Show("msg[0:4]", msg[0:4])
s.Show("msg[0:5]", msg[0:5])
// default indexes
s.Show("msg[0:]", msg[0:])
s.Show("msg[:5]", msg[:5])
s.Show("msg[:]", msg[:])
// error: beyond
// s.Show("msg", msg)[:6]
s.Show("msg[1:4]", msg[1:4])
s.Show("msg[1:5]", msg[1:5])
s.Show("msg[1:]", msg[1:])
s.Show("append(msg)", append(msg[:4], '!'))
}
================================================
FILE: 16-slices/06-slice-expressions/2-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
s "github.com/inancgumus/prettyslice"
)
func main() {
// think of this as search results of a search engine.
// it could have been fetched from a database
items := []string{
"pacman", "mario", "tetris", "doom",
"galaga", "frogger", "asteroids", "simcity",
"metroid", "defender", "rayman", "tempest",
"ultima",
}
s.MaxPerLine = 4
s.Show("All items", items)
top3 := items[:3]
s.Show("Top 3 items", top3)
l := len(items)
// you can use variables in a slice expression
last4 := items[l-4:]
s.Show("Last 4 items", last4)
// reslicing: slicing another sliced slice
mid := last4[1:3]
s.Show("Last4[1:3]", mid)
// the same elements can be in different indexes
// fmt.Println(items[9], last4[0])
// slicing returns a slice with the same type of the sliced slice
fmt.Printf("slicing : %T %[1]q\n", items[2:3])
// indexing returns a single element with the type of the indexed slice's element type
fmt.Printf("indexing: %T %[1]q\n", items[2])
}
================================================
FILE: 16-slices/07-slice-expressions-pagination/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
s "github.com/inancgumus/prettyslice"
)
func main() {
// think of this as search results of a search engine.
// it could have been fetched from a database
items := []string{
"pacman", "mario", "tetris", "doom",
"galaga", "frogger", "asteroids", "simcity",
"metroid", "defender", "rayman", "tempest",
"ultima",
}
// s.Show("0:4", items[0:4])
// s.Show("4:8", items[4:8])
// s.Show("8:12", items[8:12])
// s.Show("12:13", items[12:13])
// s.Show("12:14", items[12:14]) // error
l := len(items)
const pageSize = 4
for from := 0; from < l; from += pageSize {
to := from + pageSize
if to > l {
to = l
}
// fmt.Printf("%d:%d\n", from, to)
currentPage := items[from:to]
head := fmt.Sprintf("Page #%d", (from/pageSize)+1)
s.Show(head, currentPage)
}
}
================================================
FILE: 16-slices/08-slice-internals-1-backing-array/1-theory/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import s "github.com/inancgumus/prettyslice"
func main() {
// ages, first and last2 have the same backing arrays
ages := []int{35, 15, 25}
first := ages[0:1]
last2 := ages[1:3]
ages[0] = 55
ages[1] = 10
ages[2] = 20
// grades and ages have separate backing arrays
grades := []int{70, 99}
grades[0] = 50
s.Show("ages", ages)
s.Show("ages[0:1]", first)
s.Show("ages[1:3]", last2)
s.Show("grades", grades)
// let's create a new scope
// 'cause I'm going to use variables with the same name
{
// ages and agesArray have the same backing arrays
agesArray := [3]int{35, 15, 25}
ages := agesArray[0:3]
ages[0] = 100
ages[2] = 50
s.Show("agesArray", agesArray[:])
s.Show("agesArray's ages", ages)
}
}
================================================
FILE: 16-slices/08-slice-internals-1-backing-array/2-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
func main() {
// #1: arrays and non-empty slice literals create an array.
// For the arrays, it's explicit, but for the slices,
// it's done implicitly, behind the scenes.
grades := [...]float64{40, 10, 20, 50, 60, 70} // #1
// grades := []float64{40, 10, 20, 50, 60, 70} // #4
// #5: let's break the connection
// #6: comment-out
// var newGrades []float64
// newGrades = append(newGrades, grades...)
// #6: shortcut: []float64(nil) is a nil float64 slice
// newGrades := append([]float64(nil), grades...)
// #2: cheap: slicing doesn't allocate new memory (array).
// front := grades[:3]
// front := newGrades[:3] // #5
// #3: sort its first segment
// sort.Float64s(front)
// #7: new slices look at the same backing array
// front, front2, front3, newGrades, they all have the same backing array
// front2 := front[:3]
// front3 := front
s.PrintBacking = true // #1
s.MaxPerLine = 7 // #1
s.Show("grades", grades[:]) // #1
// s.Show("newGrades", newGrades) // #5
// s.Show("front", front) // #2
// s.Show("front2", front2) // #7
// s.Show("front3", front3) // #7
}
================================================
FILE: 16-slices/09-slice-internals-2-slice-header/1-theory/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
s "github.com/inancgumus/prettyslice"
)
func main() {
//
// each int element is 4 bytes (on 64-bit)
//
// let's say the ages point to 1000th.
// ages[1:] will point to 1004th
// ages[2:] will point to 1008th and so on.
//
// they all will be looking at the same
// backing array.
//
ages := []int{35, 15, 25}
red, green := ages[0:1], ages[1:3]
s.Show("ages", ages)
s.Show("red", red)
s.Show("green", green)
fmt.Println(red[0])
// fmt.Println(red[1]) // error
// fmt.Println(red[2]) // error
{
var ages []int
s.Show("nil slice", ages)
// or just:
s.Show("nil slice", []int(nil))
}
}
================================================
FILE: 16-slices/09-slice-internals-2-slice-header/2-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"unsafe"
s "github.com/inancgumus/prettyslice"
)
// type collection [4]string // #1
type collection []string // #2
// go is pass by copy
// only the slice header is copied: 3 integer fields (24 bytes)
// think of passing an array with millions of elements instead.
func main() {
// SliceHeader lives here:
// https://golang.org/src/runtime/slice.go
s.PrintElementAddr = true
// #1
data := collection{"slices", "are", "awesome", "period", "!!" /* #5 */}
// data := collection{"slices", "are", "awesome", "period", "!!"}
change(data) // #1
s.Show("main's data", data) // #1
fmt.Printf("main's data slice's header: %p\n", &data) // #3
// ----------------------------------------------------------------------
// #4
array := [...]string{"slices", "are", "awesome", "period", "!!" /* #5 */}
// array's size depends on its elements
fmt.Printf("array's size: %d bytes.\n", unsafe.Sizeof(array))
// slice's size is always fixed: 24 bytes (on a 64-bit system) — slice value = slice header
fmt.Printf("slice's size: %d bytes.\n", unsafe.Sizeof(data))
}
// #1
// passed value will be copied in the function
func change(data collection) {
// data is a new variable inside the function:
// var data collection
data[2] = "brilliant!"
s.Show("change's data", data)
fmt.Printf("change's data slice's header: %p\n", &data) // #3
}
================================================
FILE: 16-slices/10-slice-internals-3-len-cap/1-theory/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
s "github.com/inancgumus/prettyslice"
)
func main() {
s.MaxPerLine = 6
s.PrintBacking = true
ages := []int{35, 15, 25}
s.Show("ages", ages)
s.Show("ages[0:0]", ages[0:0])
for i := 1; i < 4; i++ {
txt := fmt.Sprintf("ages[%d:%d]", 0, i)
s.Show(txt, ages[0:i])
}
s.Show("append", append(ages, 50))
}
================================================
FILE: 16-slices/10-slice-internals-3-len-cap/2-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
func main() {
s.PrintBacking = true
// ----------------------------------------------------
// #1 nil slice
var games []string // nil slice
s.Show("games", games)
// ----------------------------------------------------
// #2 empty slice
games = []string{} // empty slice
s.Show("games", games)
// s.Show("another empty", []int{})
// ----------------------------------------------------
// #3 non-empty slice
games = []string{"pacman", "mario", "tetris", "doom"}
s.Show("games", games)
// ----------------------------------------------------
// #4 reset the part using the games slice
// part is empty but its cap is still 4
part := games
s.Show("part", part)
part = games[:0]
s.Show("part[:0]", part)
s.Show("part[:cap]", part[:cap(part)])
for cap(part) != 0 {
part = part[1:cap(part)]
s.Show("part", part)
}
// #6 backing array's elements become inaccessible
// games = games[len(games):]
// ----------------------------------------------------
// #5 part doesn't have any more capacity
// games slice is still intact
s.Show("part", part)
s.Show("games", games)
}
================================================
FILE: 16-slices/11-slice-internals-4-append/1-theory/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
func main() {
s.PrintBacking = true
ages := []int{35, 15}
s.Show("ages", ages)
ages = append(ages, 5)
s.Show("append(ages, 5)", ages)
}
================================================
FILE: 16-slices/11-slice-internals-4-append/2-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
func main() {
s.PrintBacking = true
// #1: a nil slice has no backing array
var nums []int
s.Show("no backing array", nums)
// #2: creates a new backing array
nums = append(nums, 1, 3)
s.Show("allocates", nums)
// #3: creates a new backing array
nums = append(nums, 2)
s.Show("free capacity", nums)
// #4: uses the same backing array
nums = append(nums, 4)
s.Show("no allocation", nums)
// GOAL: append new odd numbers in the middle
// [1 3 2 4] -> [1 3 7 9 2 4]
// #5: [1 3 2 4] -> [1 3 2 4 2 4]
nums = append(nums, nums[2:]...)
s.Show("nums <- nums[2:]", nums)
// #6: overwrites: [1 3 2 4 2 4] -> [1 3 7 9]
nums = append(nums[:2], 7, 9)
s.Show("nums[:2] <- 7, 9", nums)
// #7: [1 3 7 9] -> [1 3 7 9 2 4]
nums = nums[:6]
s.Show("nums: extend", nums)
}
// don't mind about these options
// they're just for printing the slices nicely
func init() {
s.MaxPerLine = 10
s.Width = 45
}
================================================
FILE: 16-slices/11-slice-internals-4-append/3-example-growth/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"math/rand"
"time"
s "github.com/inancgumus/prettyslice"
"github.com/inancgumus/screen"
)
func main() {
s.PrintBacking = true
s.MaxPerLine = 30
s.Width = 150
var nums []int
screen.Clear()
for cap(nums) <= 128 {
screen.MoveTopLeft()
s.Show("nums", nums)
nums = append(nums, rand.Intn(9)+1)
time.Sleep(time.Second / 4)
}
}
================================================
FILE: 16-slices/11-slice-internals-4-append/4-example-growth/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
ages, oldCap := []int{1}, 1.
for len(ages) < 5e5 {
ages = append(ages, 1)
c := float64(cap(ages))
if c != oldCap {
fmt.Printf("len:%-10d cap:%-10g growth:%.2f\n",
len(ages), c, c/oldCap)
}
oldCap = c
}
}
================================================
FILE: 16-slices/12-full-slice-expressions/1-theory/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
func main() {
s.PrintBacking = true
sliceable := []byte{'f', 'u', 'l', 'l'}
s.Show("sliceable", sliceable)
s.Show("sliceable[0:3]", sliceable[0:3])
s.Show("sliceable[0:3:3]", sliceable[0:3:3])
s.Show("sliceable[0:2:2]", sliceable[0:2:2])
s.Show("sliceable[0:1:1]", sliceable[0:1:1])
s.Show("sliceable[1:3:3]", sliceable[1:3:3])
s.Show("sliceable[2:3:3]", sliceable[2:3:3])
s.Show("sliceable[2:3:4]", sliceable[2:3:4])
s.Show("sliceable[4:4:4]", sliceable[4:4:4])
}
================================================
FILE: 16-slices/12-full-slice-expressions/2-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
func main() {
s.PrintBacking = true
nums := []int{1, 3, 2, 4} // #1
// odds := nums[:2] // #2
// odds := nums[:2:2] // #4
// odds = append(odds, 5, 7) // #3
// odds := append(nums[:2:2], 5, 7) // #5
// evens := append(nums[2:4], 6, 8) // #6
s.Show("nums", nums) // #1
// s.Show("odds", odds) // #2
// s.Show("evens", evens) // #6
}
// don't mind about these options
// they're just for printing the slices nicely
func init() {
s.MaxPerLine = 10
s.Width = 55
}
================================================
FILE: 16-slices/13-make/1-theory/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
prettyslice "github.com/inancgumus/prettyslice"
)
func main() {
prettyslice.PrintBacking = true
prettyslice.Show("make([]int, 3)", make([]int, 3))
prettyslice.Show("make([]int, 3, 5)", make([]int, 3, 5))
s := make([]int, 0, 5)
prettyslice.Show("make([]int, 0, 5)", s)
s = append(s, 42)
prettyslice.Show("s = append(s, 42)", s)
}
================================================
FILE: 16-slices/13-make/2-example/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"strings"
s "github.com/inancgumus/prettyslice"
)
func main() {
s.PrintBacking = true
s.MaxPerLine = 10
// #1: assume that tasks can be a long list
// ---------------------------------------------
tasks := []string{"jump", "run", "read"}
// #2: INEFFICIENT WAY
// ---------------------------------------------
// var upTasks []string
// s.Show("upTasks", upTasks)
// for _, task := range tasks {
// upTasks = append(upTasks, strings.ToUpper(task))
// s.Show("upTasks", upTasks)
// }
// #3: SO SO WAY:
// ---------------------------------------------
// upTasks := make([]string, len(tasks))
// s.Show("upTasks", upTasks)
// for _, task := range tasks {
// upTasks = append(upTasks, strings.ToUpper(task))
// s.Show("upTasks", upTasks)
// }
// #4: SO SO WAY 2:
// ---------------------------------------------
// upTasks := make([]string, len(tasks))
// s.Show("upTasks", upTasks)
// for i, task := range tasks {
// upTasks[i] = strings.ToUpper(task)
// s.Show("upTasks", upTasks)
// }
// #5: allocates a new array
// upTasks = append(upTasks, "PLAY")
// s.Show("upTasks", upTasks)
// #6: SO SO WAY 3
// ---------------------------------------------
// upTasks := make([]string, 0, len(tasks))
// #7
// upTasks = upTasks[:cap(upTasks)]
// #6
// s.Show("upTasks", upTasks)
// for i, task := range tasks {
// upTasks[i] = strings.ToUpper(task)
// s.Show("upTasks", upTasks)
// }
// #8: THE BEST WAY
// ---------------------------------------------
upTasks := make([]string, 0, len(tasks))
s.Show("upTasks", upTasks)
for _, task := range tasks {
upTasks = append(upTasks, strings.ToUpper(task))
s.Show("upTasks", upTasks)
}
}
================================================
FILE: 16-slices/14-copy/01-usage/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
s "github.com/inancgumus/prettyslice"
)
func main() {
evens := []int{2, 4}
odds := []int{3, 5, 7}
s.Show("evens [before]", evens)
s.Show("odds [before]", odds)
N := copy(evens, odds)
fmt.Printf("%d element(s) are copied.\n", N)
s.Show("evens [after]", evens)
s.Show("odds [after]", odds)
}
================================================
FILE: 16-slices/14-copy/02-hacker-incident/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
s "github.com/inancgumus/prettyslice"
)
func main() {
// #1: received the raining probabilities
data := []float64{10, 25, 30, 50}
// #2: received new data
// newData := []float64{80, 90}
// for i := 0; i < len(newData); i++ {
// data[i] = newData[i]
// }
// #3: use copy
// copy(data, []float64{99, 100})
// #4: received more data than the original
// copy(data, []float64{10, 5, 15, 0, 20})
// #5: returns the # of copied elements
// n := copy(data, []float64{10, 5, 15, 0, 20})
// fmt.Printf("%d probabilities copied.\n", n)
// #6: (sometimes) use append instead of copy
// data = append(data[:0], []float64{10, 5, 15, 0, 20}...)
// #7: clone a slice using copy
// saved := make([]float64, len(data))
// copy(saved, data)
// #9: clone a slice using append nil (I prefer this)
// saved := append([]float64(nil), data...)
// data[0] = 0 // #8
// s.Show("Probabilities (saved)", saved) // #7
// #1: print the probabilities
s.Show("Probabilities (data)", data)
fmt.Printf("Is it gonna rain? %.f%% chance.\n",
(data[0]+data[1]+data[2]+data[3])/
float64(len(data)))
}
================================================
FILE: 16-slices/15-multi-dimensional-slices/version-1/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
// 1st day: $200, $100
// 2nd day: $500
// 3rd day: $50, $25, and $75
spendings := [][]int{
{200, 100}, // 1st day
{500}, // 2nd day
{50, 25, 75}, // 3rd day
}
for i, daily := range spendings {
var total int
for _, spending := range daily {
total += spending
}
fmt.Printf("Day %d: %d\n", i+1, total)
}
}
================================================
FILE: 16-slices/15-multi-dimensional-slices/version-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
spendings := make([][]int, 0, 5)
spendings = append(spendings, []int{200, 100})
spendings = append(spendings, []int{25, 10, 45, 60})
spendings = append(spendings, []int{5, 15, 35})
spendings = append(spendings, []int{95, 10}, []int{50, 25})
for i, daily := range spendings {
var total int
for _, spending := range daily {
total += spending
}
fmt.Printf("Day %d: %d\n", i+1, total)
}
}
================================================
FILE: 16-slices/15-multi-dimensional-slices/version-3/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
spendings := fetch()
for i, daily := range spendings {
var total int
for _, spending := range daily {
total += spending
}
fmt.Printf("Day %d: %d\n", i+1, total)
}
}
func fetch() [][]int {
content := `200 100
25 10 45 60
5 15 35
95 10
50 25`
lines := strings.Split(content, "\n")
spendings := make([][]int, len(lines))
for i, line := range lines {
fields := strings.Fields(line)
spendings[i] = make([]int, len(fields))
for j, field := range fields {
spending, _ := strconv.Atoi(field)
spendings[i][j] = spending
}
}
return spendings
}
================================================
FILE: 16-slices/README.md
================================================
# WARNING
For the code in this section, you should install my prettyslice library.
## STEPS
1. Open your command-line
2. Type: `go get -u github.com/inancgumus/prettyslice`
3. That's all.
================================================
FILE: 16-slices/exercises/01-declare-nil/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Declare nil slices
//
// 1. Declare the following slices as nil slices:
//
// 1. The names of your friends (names slice)
//
// 2. The distances to locations (distances slice)
//
// 3. A data buffer (data slice)
//
// 4. Currency exchange ratios (ratios slice)
//
// 5. Up/Down status of web servers (alives slice)
//
//
// 2. Print their type, length and whether they're equal to nil value or not.
//
//
// EXPECTED OUTPUT
// names : []string 0 true
// distances: []int 0 true
// data : []uint8 0 true
// ratios : []float64 0 true
// alives : []bool 0 true
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 16-slices/exercises/01-declare-nil/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
names []string // The names of your friends
distances []int // The distances
data []byte // A data buffer
ratios []float64 // Currency exchange ratios
alives []bool // Up/Down status of web servers
)
fmt.Printf("names : %T %d %t\n", names, len(names), names == nil)
fmt.Printf("distances: %T %d %t\n", distances, len(distances), distances == nil)
fmt.Printf("data : %T %d %t\n", data, len(data), data == nil)
fmt.Printf("ratios : %T %d %t\n", ratios, len(ratios), ratios == nil)
fmt.Printf("alives : %T %d %t\n", alives, len(alives), alives == nil)
}
================================================
FILE: 16-slices/exercises/02-empty/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Assign empty slices
//
// Assign empty slices to all the slices that you've declared in the previous
// exercise, and print them here.
//
//
// EXPECTED OUTPUT
// names : []string 0 false
// distances: []int 0 false
// data : []uint8 0 false
// ratios : []float64 0 false
// alives : []bool 0 false
// ---------------------------------------------------------
func main() {
var (
names []string // The names of your friends
distances []int // The distances
data []byte // A data buffer
ratios []float64 // Currency exchange ratios
alives []bool // Up/Down status of web servers
)
fmt.Printf("names : %T %d %t\n", names, len(names), names == nil)
fmt.Printf("distances: %T %d %t\n", distances, len(distances), distances == nil)
fmt.Printf("data : %T %d %t\n", data, len(data), data == nil)
fmt.Printf("ratios : %T %d %t\n", ratios, len(ratios), ratios == nil)
fmt.Printf("alives : %T %d %t\n", alives, len(alives), alives == nil)
}
================================================
FILE: 16-slices/exercises/02-empty/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
names []string // The names of your friends
distances []int // The distances
data []byte // A data buffer
ratios []float64 // Currency exchange ratios
alives []bool // Up/Down status of web servers
)
names = []string{}
distances = []int{}
data = []byte{}
ratios = []float64{}
alives = []bool{}
fmt.Printf("names : %T %d %t\n", names, len(names), names == nil)
fmt.Printf("distances: %T %d %t\n", distances, len(distances), distances == nil)
fmt.Printf("data : %T %d %t\n", data, len(data), data == nil)
fmt.Printf("ratios : %T %d %t\n", ratios, len(ratios), ratios == nil)
fmt.Printf("alives : %T %d %t\n", alives, len(alives), alives == nil)
}
================================================
FILE: 16-slices/exercises/03-slice-literal/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Assign slice literals
//
// 1. Assign the following data using slice literals to the slices that
// you've declared in the first exercise.
//
// 1. The names of your three best friends (to the names slice)
//
// 2. The distances to five different locations (to the distances slice)
//
// 3. Five bytes of data (to the data slice)
//
// 4. Two currency exchange ratios (to the ratios slice)
//
// 5. Up/Down status of four different web servers (to the alives slice)
//
// 2. Print their type, length and whether they're equal to nil value or not
//
// 3. Compare the length of the distances and the data slices; print a message
// if they are equal (use an if statement).
//
//
// EXPECTED OUTPUT
// names : []string 3 false
// distances: []int 5 false
// data : []uint8 5 false
// ratios : []float64 2 false
// alives : []bool 4 false
// The length of the distances and the data slices are the same.
// ---------------------------------------------------------
func main() {
var (
names []string // The names of your friends
distances []int // The distances
data []byte // A data buffer
ratios []float64 // Currency exchange ratios
alives []bool // Up/Down status of web servers
)
names = []string{}
distances = []int{}
data = []byte{}
ratios = []float64{}
alives = []bool{}
fmt.Printf("names : %T %d %t\n", names, len(names), names == nil)
fmt.Printf("distances: %T %d %t\n", distances, len(distances), distances == nil)
fmt.Printf("data : %T %d %t\n", data, len(data), data == nil)
fmt.Printf("ratios : %T %d %t\n", ratios, len(ratios), ratios == nil)
fmt.Printf("alives : %T %d %t\n", alives, len(alives), alives == nil)
}
================================================
FILE: 16-slices/exercises/03-slice-literal/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
names []string // The names of your friends
distances []int // The distances
data []byte // A data buffer
ratios []float64 // Currency exchange ratios
alives []bool // Up/Down status of web servers
)
names = []string{"serpil", "ebru", "lina"}
distances = []int{100, 200, 300, 400, 500}
data = []byte{'I', 'N', 'A', 'N', 'C'}
ratios = []float64{3.14, 6.28}
alives = []bool{true, false, false, true}
fmt.Printf("names : %T %d %t\n", names, len(names), names == nil)
fmt.Printf("distances: %T %d %t\n", distances, len(distances), distances == nil)
fmt.Printf("data : %T %d %t\n", data, len(data), data == nil)
fmt.Printf("ratios : %T %d %t\n", ratios, len(ratios), ratios == nil)
fmt.Printf("alives : %T %d %t\n", alives, len(alives), alives == nil)
if len(distances) == len(data) {
fmt.Println("The length of the distances and the data slices are the same.")
}
}
================================================
FILE: 16-slices/exercises/04-declare-arrays-as-slices/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Declare the arrays as slices
//
// 1. First run the following program as it is
//
// 2. Then change the array declarations to slice declarations
//
// 3. Observe whether anything changes or not (on the surface :)).
//
// EXPECTED OUTPUT
// names : []string ["Einstein" "Tesla" "Shepard"]
// distances: []int [50 40 75 30 125]
// data : []uint8 [72 69 76 76 79]
// ratios : []float64 [3.14]
// alives : []bool [true false true false]
// zero : []uint8 []
// ---------------------------------------------------------
func main() {
names := [3]string{"Einstein", "Tesla", "Shepard"}
distances := [...]int{50, 40, 75, 30, 125}
data := [5]byte{'H', 'E', 'L', 'L', 'O'}
ratios := [1]float64{3.14145}
alives := [...]bool{true, false, true, false}
zero := [0]byte{}
fmt.Printf("names : %[1]T %[1]q\n", names)
fmt.Printf("distances: %[1]T %[1]d\n", distances)
fmt.Printf("data : %[1]T %[1]d\n", data)
fmt.Printf("ratios : %[1]T %.2[1]f\n", ratios)
fmt.Printf("alives : %[1]T %[1]t\n", alives)
fmt.Printf("zero : %[1]T %[1]d\n", zero)
}
================================================
FILE: 16-slices/exercises/04-declare-arrays-as-slices/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
names := []string{"Einstein", "Tesla", "Shepard"}
distances := []int{50, 40, 75, 30, 125}
data := []byte{'H', 'E', 'L', 'L', 'O'}
ratios := []float64{3.14145}
alives := []bool{true, false, true, false}
zero := []byte{}
fmt.Printf("names : %[1]T %[1]q\n", names)
fmt.Printf("distances: %[1]T %[1]d\n", distances)
fmt.Printf("data : %[1]T %[1]d\n", data)
fmt.Printf("ratios : %[1]T %.2[1]f\n", ratios)
fmt.Printf("alives : %[1]T %[1]t\n", alives)
fmt.Printf("zero : %[1]T %[1]d\n", zero)
}
================================================
FILE: 16-slices/exercises/05-fix-the-problems/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Fix the problems
//
// 1. Uncomment the code
//
// 2. Fix the problems
//
// 3. BONUS: Simplify the code
//
//
// EXPECTED OUTPUT
// "Einstein and Shepard and Tesla"
// ["Fire" "Kafka's Revenge" "Stay Golden"]
// [1 2 3 5 6 7 8 9]
// ---------------------------------------------------------
func main() {
// var names []string
// names := []string{}
// names = [...]string{
// "Einstein" "Shepard"
// "Tesla"
// }
// -----------------------------------
// var books []string = [3]string{
// "Stay Golden",
// "Fire",
// "Kafka's Revenge",
// }
// sort.Strings(books)
// -----------------------------------
// // this time, do not change the nums array to a slice
// nums := [...]int{5,1,7,3,8,2,6,9}
// // use the slicing expression to change the nums array to a slice below
// sort.Ints(nums)
// -----------------------------------
// Here: Use the strings.Join function to join the names
// (see the expected output)
// fmt.Printf("%q\n", names)
// fmt.Printf("%q\n", books)
// fmt.Printf("%d\n", nums)
}
================================================
FILE: 16-slices/exercises/05-fix-the-problems/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"sort"
"strings"
)
func main() {
names := []string{"Einstein", "Shepard", "Tesla"}
books := []string{"Stay Golden", "Fire", "Kafka's Revenge"}
sort.Strings(books)
nums := [...]int{5, 1, 7, 3, 8, 2, 6, 9}
sort.Ints(nums[:])
fmt.Printf("%q\n", strings.Join(names, " and "))
fmt.Printf("%q\n", books)
fmt.Printf("%d\n", nums)
}
================================================
FILE: 16-slices/exercises/06-compare-the-slices/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Compare the slices
//
// 1. Split the namesA string and get a slice
//
// 2. Sort all the slices
//
// 3. Compare whether the slices are equal or not
//
//
// EXPECTED OUTPUT
//
// They are equal.
//
//
// HINTS
//
// 1. strings.Split function splits a string and
// returns a string slice
//
// 2. Comparing slices: First check whether their length
// are the same or not; only then compare them.
//
// ---------------------------------------------------------
func main() {
// namesA := "Da Vinci, Wozniak, Carmack"
// namesB := []string{"Wozniak", "Da Vinci", "Carmack"}
}
================================================
FILE: 16-slices/exercises/06-compare-the-slices/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"sort"
"strings"
)
func main() {
namesA := "Da Vinci, Wozniak, Carmack"
namesB := []string{"Wozniak", "Da Vinci", "Carmack"}
namesC := strings.Split(namesA, ", ")
sort.Strings(namesC)
sort.Strings(namesB)
if len(namesC) == len(namesB) {
for i := range namesC {
if namesC[i] != namesB[i] {
return
}
}
fmt.Println("They are equal.")
}
}
================================================
FILE: 16-slices/exercises/07-append/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Append
//
// Please follow the instructions within the code below.
//
// EXPECTED OUTPUT
// They are equal.
//
// HINTS
// bytes.Equal function allows you to compare two byte
// slices easily. Check its documentation: go doc bytes.Equal
// ---------------------------------------------------------
func main() {
// 1. uncomment the code below
// png, header := []byte{'P', 'N', 'G'}, []byte{}
// 2. append elements to header to make it equal with the png slice
// 3. compare the slices using the bytes.Equal function
// 4. print whether they're equal or not
}
================================================
FILE: 16-slices/exercises/07-append/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"fmt"
)
func main() {
png, header := []byte{'P', 'N', 'G'}, []byte{}
header = append(header, png...)
if bytes.Equal(png, header) {
fmt.Println("They are equal")
}
}
================================================
FILE: 16-slices/exercises/08-append-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Append #2
//
// 1. Create the following nil slices:
// + Pizza toppings
// + Departure times
// + Student graduation years
// + On/off states of lights in a room
//
// 2. Append them some elements (use your creativity!)
//
// 3. Print all the slices
//
//
// EXPECTED OUTPUT
// (Your output may change, mine is like so:)
//
// pizza : [pepperoni onions extra cheese]
//
// graduations : [1998 2005 2018]
//
// departures : [2019-01-28 15:09:31.294594 +0300 +03 m=+0.000325020
// 2019-01-29 15:09:31.294594 +0300 +03 m=+86400.000325020
// 2019-01-30 15:09:31.294594 +0300 +03 m=+172800.000325020]
//
// lights : [true false true]
//
//
// HINTS
// + For departure times, use the time.Time type. Check its documentation.
//
// now := time.Now() -> Gives you the current time
// now.Add(time.Hour*24) -> Gives you a time.Time 24 hours after `now`
//
// + For graduation years, you can use the int type
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 16-slices/exercises/08-append-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
// ------------------------------------------------------------
// Create nil slices
// ------------------------------------------------------------
// Pizza toppings
var pizza []string
// Departure times
var departures []time.Time
// Student graduation years
var grads []int
// On/off states of lights in a room
var lights []bool
// ------------------------------------------------------------
// Append them some elements (use your creativity!)
// ------------------------------------------------------------
pizza = append(pizza, "pepperoni", "onions", "extra cheese")
now := time.Now()
departures = append(departures,
now,
now.Add(time.Hour*24), // 24 hours after `now`
now.Add(time.Hour*48)) // 48 hours after `now`
grads = append(grads, 1998, 2005, 2018)
lights = append(lights, true, false, true)
// ------------------------------------------------------------
// Print the slices
// ------------------------------------------------------------
fmt.Printf("pizza : %s\n", pizza)
fmt.Printf("\ngraduations : %d\n", grads)
fmt.Printf("\ndepartures : %s\n", departures)
fmt.Printf("\nlights : %t\n", lights)
}
================================================
FILE: 16-slices/exercises/09-append-3-fix/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Append #3 — Fix the problems
//
// Fix the problems in the code below.
//
// BONUS
//
// Simplify the code.
//
// EXPECTED OUTPUT
//
// toppings: [black olives green peppers onions extra cheese]
//
// ---------------------------------------------------------
func main() {
// toppings := []int{"black olives", "green peppers"}
// var pizza [3]string
// append(pizza, ...toppings)
// pizza = append(toppings, "onions")
// toppings = append(pizza, extra cheese)
// fmt.Printf("pizza : %s\n", pizza)
}
================================================
FILE: 16-slices/exercises/09-append-3-fix/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
toppings := []string{"black olives", "green peppers"}
var pizza []string
pizza = append(pizza, toppings...)
pizza = append(pizza, "onions", "extra cheese")
fmt.Printf("toppings: %s\n", pizza)
}
================================================
FILE: 16-slices/exercises/10-append-sort-nums/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Append and Sort Numbers
//
// We'll have a []string that should contain numbers.
//
// Your task is to convert the []string to an int slice.
//
// 1. Get the numbers from the command-line
//
// 2. Append them to an []int
//
// 3. Sort the numbers
//
// 4. Print them
//
// 5. Handle the error cases
//
//
// EXPECTED OUTPUT
//
// go run main.go
// provide a few numbers
//
// go run main.go 4 6 1 3 0 9 2
// [0 1 2 3 4 6 9]
//
// go run main.go a b c
// []
//
// go run main.go 4 a 1 c d 9
// [1 4 9]
//
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 16-slices/exercises/10-append-sort-nums/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"sort"
"strconv"
)
func main() {
args := os.Args[1:]
if len(args) == 0 {
fmt.Println("provide a few numbers")
return
}
var nums []int
for _, s := range args {
n, err := strconv.Atoi(s)
if err != nil {
continue
}
nums = append(nums, n)
}
sort.Ints(nums)
fmt.Println(nums)
}
================================================
FILE: 16-slices/exercises/11-housing-prices/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Housing Prices
//
// We have received housing prices. Your task is to load the data into
// appropriately typed slices then print them.
//
// 1. Check out the expected output
//
//
// 2. Check out the code below
//
// 1. header : stores the column headers
// 2. data : stores the real data related to each column
// 3. separator: you will use it to separate the data
//
//
// 3. Parse the data
//
// 1. Separate it into rows by using the newline character ("\n")
//
// 2. For each row, separate it by using the separator (",")
//
//
// 4. Load the data into distinct slices
//
// 1. Load the locations into a []string
// 2. Load the sizes into []int
// 3. Load the beds into []int
// 4. Load the baths into []int
// 5. Load the prices into []int
//
//
// 5. Print the header
//
// 1. Separate it by using the separator
//
// 2. Print each column 15 character wide ("%-15s")
//
//
// 6. Print the rows from the slices that you've created, line by line
//
//
// EXPECTED OUTPUT
//
// Location Size Beds Baths Price
// ===========================================================================
// New York 100 2 1 100000
// New York 150 3 2 200000
// Paris 200 4 3 400000
// Istanbul 500 10 5 1000000
//
//
// HINTS
//
// + strings.Split function can separate a string into a []string
//
// ---------------------------------------------------------
func main() {
const (
header = "Location,Size,Beds,Baths,Price"
data = `New York,100,2,1,100000
New York,150,3,2,200000
Paris,200,4,3,400000
Istanbul,500,10,5,1000000`
separator = ","
)
}
================================================
FILE: 16-slices/exercises/11-housing-prices/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
const (
header = "Location,Size,Beds,Baths,Price"
data = `New York,100,2,1,100000
New York,150,3,2,200000
Paris,200,4,3,400000
Istanbul,500,10,5,1000000`
separator = ","
)
var (
locs []string
sizes, beds, baths, prices []int
)
rows := strings.Split(data, "\n")
for _, row := range rows {
cols := strings.Split(row, separator)
locs = append(locs, cols[0])
n, _ := strconv.Atoi(cols[1])
sizes = append(sizes, n)
n, _ = strconv.Atoi(cols[2])
beds = append(beds, n)
n, _ = strconv.Atoi(cols[3])
baths = append(baths, n)
n, _ = strconv.Atoi(cols[4])
prices = append(prices, n)
}
for _, h := range strings.Split(header, separator) {
fmt.Printf("%-15s", h)
}
fmt.Printf("\n%s\n", strings.Repeat("=", 75))
for i := range rows {
fmt.Printf("%-15s", locs[i])
fmt.Printf("%-15d", sizes[i])
fmt.Printf("%-15d", beds[i])
fmt.Printf("%-15d", baths[i])
fmt.Printf("%-15d", prices[i])
fmt.Println()
}
}
================================================
FILE: 16-slices/exercises/12-housing-prices-averages/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Housing Prices and Averages
//
// Use the previous exercise to solve this exercise (Housing Prices).
//
// Your task is to print the averages of the sizes, beds, baths, and prices.
//
//
// EXPECTED OUTPUT
//
// Location Size Beds Baths Price
// ===========================================================================
// New York 100 2 1 100000
// New York 150 3 2 200000
// Paris 200 4 3 400000
// Istanbul 500 10 5 1000000
//
// ===========================================================================
// 237.50 4.75 2.75 425000.00
//
// ---------------------------------------------------------
func main() {
const (
header = "Location,Size,Beds,Baths,Price"
data = `New York,100,2,1,100000
New York,150,3,2,200000
Paris,200,4,3,400000
Istanbul,500,10,5,1000000`
separator = ","
)
// Solve this exercise by using your previous solution for
// the "Housing Prices" exercise.
}
================================================
FILE: 16-slices/exercises/12-housing-prices-averages/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
const (
header = "Location,Size,Beds,Baths,Price"
data = `New York,100,2,1,100000
New York,150,3,2,200000
Paris,200,4,3,400000
Istanbul,500,10,5,1000000`
separator = ","
)
var (
locs []string
sizes, beds, baths, prices []int
)
rows := strings.Split(data, "\n")
for _, row := range rows {
cols := strings.Split(row, separator)
locs = append(locs, cols[0])
n, _ := strconv.Atoi(cols[1])
sizes = append(sizes, n)
n, _ = strconv.Atoi(cols[2])
beds = append(beds, n)
n, _ = strconv.Atoi(cols[3])
baths = append(baths, n)
n, _ = strconv.Atoi(cols[4])
prices = append(prices, n)
}
for _, h := range strings.Split(header, separator) {
fmt.Printf("%-15s", h)
}
fmt.Printf("\n%s\n", strings.Repeat("=", 75))
for i := range rows {
fmt.Printf("%-15s", locs[i])
fmt.Printf("%-15d", sizes[i])
fmt.Printf("%-15d", beds[i])
fmt.Printf("%-15d", baths[i])
fmt.Printf("%-15d", prices[i])
fmt.Println()
}
// -------------------------------------------------------------------------
// print the averages
//
// evil note:
// later on, you will see how easy it would be to solve this
// using the functions instead. there are a lot of repetitive code here.
// -------------------------------------------------------------------------
fmt.Printf("\n%s\n", strings.Repeat("=", 75))
// jump over the location column
fmt.Printf("%-15s", "")
var sum int
for _, n := range sizes {
sum += n
}
fmt.Printf("%-15.2f", float64(sum)/float64(len(sizes)))
sum = 0
for _, n := range beds {
sum += n
}
fmt.Printf("%-15.2f", float64(sum)/float64(len(beds)))
sum = 0
for _, n := range baths {
sum += n
}
fmt.Printf("%-15.2f", float64(sum)/float64(len(baths)))
sum = 0
for _, n := range prices {
sum += n
}
fmt.Printf("%-15.2f", float64(sum)/float64(len(prices)))
fmt.Println()
}
================================================
FILE: 16-slices/exercises/13-slicing-basics/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Slice the numbers
//
// We've a string that contains even and odd numbers.
//
// 1. Convert the string to an []int
//
// 2. Print the slice
//
// 3. Slice it for the even numbers and print it (assign it to a new slice variable)
//
// 4. Slice it for the odd numbers and print it (assign it to a new slice variable)
//
// 5. Slice it for the two numbers at the middle
//
// 6. Slice it for the first two numbers
//
// 7. Slice it for the last two numbers (use the len function)
//
// 8. Slice the evens slice for the last one number
//
// 9. Slice the odds slice for the last two numbers
//
//
// EXPECTED OUTPUT
// go run main.go
//
// nums : [2 4 6 1 3 5]
// evens : [2 4 6]
// odds : [1 3 5]
// middle : [6 1]
// first 2 : [2 4]
// last 2 : [3 5]
// evens last 1: [6]
// odds last 2 : [3 5]
//
//
// NOTE
//
// You can also use my prettyslice package for printing the slices.
//
//
// HINT
//
// Find a function in the strings package for splitting the string into []string
//
// ---------------------------------------------------------
func main() {
// uncomment the declaration below
// data := "2 4 6 1 3 5"
}
================================================
FILE: 16-slices/exercises/13-slicing-basics/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
data := "2 4 6 1 3 5"
splitted := strings.Fields(data)
var nums []int
for _, s := range splitted {
n, _ := strconv.Atoi(s)
nums = append(nums, n)
}
// rest of the code for this exercise
fmt.Println("nums :", nums)
evens, odds := nums[:3], nums[3:]
fmt.Println("evens :", evens)
fmt.Println("odds :", odds)
fmt.Println("middle :", nums[2:4])
fmt.Println("first 2 :", nums[:2])
fmt.Println("last 2 :", nums[len(nums)-2:])
fmt.Println("evens last 1:", evens[len(evens)-1:])
fmt.Println("odds last 2 :", odds[len(odds)-2:])
}
================================================
FILE: 16-slices/exercises/14-slicing-by-args/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Slicing by arguments
//
// We've a []string, you will get arguments from the command-line,
// then you will print only the elements that are requested.
//
// 1. Print the []string (it's in the code below)
//
// 2. Get the starting and stopping positions from the command-line
//
// 3. Print the []string slice by slicing it using the starting and stopping
// positions
//
// 4. Handle the error cases (see the expected output below)
//
// 5. Add new elements to the []string slice literal.
// Your program should work without changing the rest of the code.
//
// 6. Now, play with your program, get a deeper sense of how the slicing
// works.
//
//
// EXPECTED OUTPUT
//
// go run main.go
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// Provide only the [starting] and [stopping] positions
//
//
// (error because: we expect only two arguments)
//
// go run main.go 1 2 4
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// Provide only the [starting] and [stopping] positions
//
//
// (error because: starting index >= 0 && stopping pos <= len(slice) )
//
// go run main.go -1 5
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// Wrong positions
//
//
// (error because: starting <= stopping)
//
// go run main.go 3 2
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// Wrong positions
//
//
// go run main.go 0
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// [Normandy Verrikan Nexus Warsaw]
//
//
// go run main.go 1
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// [Verrikan Nexus Warsaw]
//
//
// go run main.go 2
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// [Nexus Warsaw]
//
//
// go run main.go 3
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// [Warsaw]
//
//
// go run main.go 4
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// []
//
//
// go run main.go 0 3
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// [Normandy Verrikan Nexus]
//
//
// go run main.go 1 3
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// [Verrikan Nexus]
//
//
// go run main.go 1 2
// ["Normandy" "Verrikan" "Nexus" "Warsaw"]
//
// [Verrikan]
//
// ---------------------------------------------------------
func main() {
// uncomment the slice below
// ships := []string{"Normandy", "Verrikan", "Nexus", "Warsaw"}
}
================================================
FILE: 16-slices/exercises/14-slicing-by-args/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
ships := []string{"Normandy", "Verrikan", "Nexus", "Warsaw"}
fmt.Printf("%q\n\n", ships)
from, to := 0, len(ships)
switch poss := os.Args[1:]; len(poss) {
default:
fallthrough
case 0:
fmt.Println("Provide only the [starting] and [stopping] positions")
return
case 2:
to, _ = strconv.Atoi(poss[1])
fallthrough
case 1:
from, _ = strconv.Atoi(poss[0])
}
if l := len(ships); from < 0 || from > l || to > l || from > to {
fmt.Println("Wrong positions")
return
}
fmt.Println(ships[from:to])
}
================================================
FILE: 16-slices/exercises/15-slicing-housing-prices/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Slicing the Housing Prices
//
// We have received housing prices. Your task is to print only the requested
// columns of data (see the expected output).
//
// 1. Separate the data by the newline ("\n") -> rows
//
// 2. Separate each row of the data by the separator (",") -> columns
//
// 3. Find the from and to positions inside the columns depending
// on the command-line arguments.
//
// 4. Print only the requested column headers and their data
//
//
// RESTRICTIONS
//
// + You should use slicing when printing the columns.
//
//
// EXPECTED OUTPUT
//
// go run main.go
// Location Size Beds Baths Price
//
// New York 100 2 1 100000
// New York 150 3 2 200000
// Paris 200 4 3 400000
// Istanbul 500 10 5 1000000
//
//
// go run main.go Location
// Location Size Beds Baths Price
//
// New York 100 2 1 100000
// New York 150 3 2 200000
// Paris 200 4 3 400000
// Istanbul 500 10 5 1000000
//
//
// NOTE : Finds the position of the Size column and slices the columns
// appropriately.
//
// go run main.go Size
// Size Beds Baths Price
//
// 100 2 1 100000
// 150 3 2 200000
// 200 4 3 400000
// 500 10 5 1000000
//
//
// NOTE : Finds the positions of the Size and Baths columns and
// slices the columns appropriately.
//
// go run main.go Size Baths
// Size Beds Baths
//
// 100 2 1
// 150 3 2
// 200 4 3
// 500 10 5
//
//
// go run main.go Beds Price
// Beds Baths Price
//
// 2 1 100000
// 3 2 200000
// 4 3 400000
// 10 5 1000000
//
//
// Note : It works even if the given column name does not exist.
//
// go run main.go Beds NotExist
// Beds Baths Price
//
// 2 1 100000
// 3 2 200000
// 4 3 400000
// 10 5 1000000
//
//
// go run main.go NotExist NotExist
// Location Size Beds Baths Price
//
// New York 100 2 1 100000
// New York 150 3 2 200000
// Paris 200 4 3 400000
// Istanbul 500 10 5 1000000
//
//
// Note : It works even if the Price's index > Size's index
//
// In that case, it resets the invalid starting position to 0.
//
// But it still uses the Size column.
//
// go run main.go Price Size
// Location Size
//
// New York 100
// New York 150
// Paris 200
// Istanbul 500
//
//
// HINTS
//
// + strings.Split function can separate a string into a []string
//
// ---------------------------------------------------------
func main() {
const (
data = `Location,Size,Beds,Baths,Price
New York,100,2,1,100000
New York,150,3,2,200000
Paris,200,4,3,400000
Istanbul,500,10,5,1000000`
separator = ","
)
}
================================================
FILE: 16-slices/exercises/15-slicing-housing-prices/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
)
func main() {
const (
data = `Location,Size,Beds,Baths,Price
New York,100,2,1,100000
New York,150,3,2,200000
Paris,200,4,3,400000
Istanbul,500,10,5,1000000`
separator = ","
)
// parse the data
rows := strings.Split(data, "\n")
cols := strings.Split(rows[0], separator)
// default case: slice for all the columns
from, to := 0, len(cols)
// find the from and to positions depending on the command-line arguments
args := os.Args[1:]
for i, v := range cols {
l := len(args)
if l >= 1 && v == args[0] {
from = i
}
if l == 2 && v == args[1] {
to = i + 1 // +1 because the stopping index is a position
}
}
// "from" cannot be greater than or equal to "to": reset invalid arg to 0
if from >= to {
from = 0
}
for i, row := range rows {
cols := strings.Split(row, separator)
// print only the requested columns
for _, h := range cols[from:to] {
fmt.Printf("%-15s", h)
}
fmt.Println()
// print extra new line for the header
if i == 0 {
fmt.Println()
}
}
}
================================================
FILE: 16-slices/exercises/16-internals-backing-array-fix/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// ---------------------------------------------------------
// EXERCISE: Fix the backing array problem
//
// Ensure that changing the elements of the `mine` slice
// does not change the elements of the `nums` slice.
//
//
// CURRENT OUTPUT (INCORRECT)
//
// Mine : [-50 -100 -150 25 30 50]
// Original nums: [-50 -100 -150]
//
//
// EXPECTED OUTPUT
//
// Mine : [-50 -100 -150]
// Original nums: [56 89 15]
//
// ---------------------------------------------------------
func main() {
// DON'T TOUCH THE FOLLOWING CODE
nums := []int{56, 89, 15, 25, 30, 50}
// ----------------------------------------
// ONLY ADD YOUR CODE HERE
//
// Ensure that nums slice never changes even though
// the mine slice changes.
mine := nums
// ----------------------------------------
// DON'T TOUCH THE FOLLOWING CODE
//
// This code changes the elements of the nums
// slice.
//
mine[0], mine[1], mine[2] = -50, -100, -150
fmt.Println("Mine :", mine)
fmt.Println("Original nums:", nums[:3])
}
================================================
FILE: 16-slices/exercises/16-internals-backing-array-fix/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
nums := []int{56, 89, 15, 25, 30, 50}
// ----------------------------------------
// breaks the connection:
// mine and nums now have different backing arrays
// verbose solution:
// var mine []int
// mine = append(mine, nums[:3]...)
// better solution (almost the same thing):
mine := append([]int(nil), nums[:3]...)
// ----------------------------------------
mine[0], mine[1], mine[2] = -50, -100, -150
fmt.Println("Mine :", mine)
fmt.Println("Original nums:", nums[:3])
}
================================================
FILE: 16-slices/exercises/17-internals-backing-array-sort/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// ---------------------------------------------------------
// EXERCISE: Sort the backing array
//
// 1. Sort only the middle 3 items.
//
// 2. All the slices should see your changes.
//
//
// RESTRICTION
//
// Do not sort manually. Sort by using the sort package.
//
//
// EXPECTED OUTPUT
//
// Original: [pacman mario tetris doom galaga frogger asteroids simcity metroid defender rayman tempest ultima]
//
// Sorted : [pacman mario tetris doom galaga asteroids frogger simcity metroid defender rayman tempest ultima]
//
//
// HINT:
//
// Middle items are : [frogger asteroids simcity]
//
// After sorting they become: [asteroids frogger simcity]
//
// ---------------------------------------------------------
func main() {
items := []string{
"pacman", "mario", "tetris", "doom", "galaga", "frogger",
"asteroids", "simcity", "metroid", "defender", "rayman",
"tempest", "ultima",
}
fmt.Println("Original:", items)
// ADD YOUR CODE HERE
fmt.Println()
fmt.Println("Sorted :", items)
}
================================================
FILE: 16-slices/exercises/17-internals-backing-array-sort/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"sort"
)
func main() {
items := []string{
"pacman", "mario", "tetris", "doom", "galaga", "frogger",
"asteroids", "simcity", "metroid", "defender", "rayman",
"tempest", "ultima",
}
fmt.Println("Original:", items)
mid := len(items) / 2
smid := items[mid-1 : mid+2]
// sorting the smid will affect the items
// as well. their backing array is the same.
sort.Strings(smid)
fmt.Println()
fmt.Println("Sorted :", items)
}
================================================
FILE: 16-slices/exercises/18-internals-slice-header/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"runtime"
"runtime/debug"
)
// ---------------------------------------------------------
// EXERCISE: Observe the memory allocations
//
// In this exercise, your goal is to observe the memory allocation
// differences between arrays and slices.
//
// You will create, assign arrays and slices then you will print
// the memory usage of your program on each step.
//
// Please follow the instructions inside the code.
//
//
// EXPECTED OUTPUT
//
// Note that, your memory usage numbers may vary. However, the size of the
// arrays and slices should be the same on your own system as well
// (if you're on a 64-bit machine).
//
//
// [initial memory usage]
// > Memory Usage: 104 KB
// [after declaring an array]
// > Memory Usage: 78235 KB
// [after copying the array]
// > Memory Usage: 156365 KB
// [inside passArray]
// > Memory Usage: 234495 KB
// [after slicings]
// > Memory Usage: 234497 KB
// [inside passSlice]
// > Memory Usage: 234497 KB
//
// Array's size : 80000000 bytes.
// Array2's size: 80000000 bytes.
// Slice1's size: 24 bytes.
// Slice2's size: 24 bytes.
// Slice3's size: 24 bytes.
//
//
// HINTS
//
// I've declared a few functions to help you.
//
// report function:
// - Prints the memory usage.
// - Just call it with a message that matches to the expected output.
//
// passArray function:
// - It automatically prints the memory usage.
// - Accepts a [size]int array, so you can pass your array to it.
//
// passSlice function:
// - It automatically prints the memory usage.
// - Accepts an int slice, so you can pass it one of your slices.
//
// ---------------------------------------------------------
const size = 1e7
func main() {
// don't worry about this code.
// it stops the garbage collector: prevents cleaning up the memory.
// see the link if you're curious:
// https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)
debug.SetGCPercent(-1)
// run the program to see the initial memory usage.
report("initial memory usage")
// 1. allocate an array with 10 million int elements
// the array's size will be equal to ~80MB
// hint: use the `size` constant above.
// 2. print the memory usage (use the report func).
// 3. copy the array to a new array.
// 4. print the memory usage
// 5. pass the array to the passArray function
// 6. convert one of the arrays to a slice
// 7. slice only the first 1000 elements of the array
// 8. slice only the elements of the array between 1000 and 10000
// 9. print the memory usage (report func)
// 10. pass the one of the slices to the passSlice function
// 11. print the sizes of the arrays and slices
// hint: use the unsafe.Sizeof function
// see more here: https://golang.org/pkg/unsafe/#Sizeof
}
// passes [size]int array — about 80MB!
//
// observe that passing an array to a function (or assigning it to a variable)
// affects the memory usage dramatically
func passArray(items [size]int) {
items[0] = 100
report("inside passArray")
}
// only passes 24-bytes of slice header
//
// observe that passing a slice doesn't affect the memory usage
func passSlice(items []int) {
items[0] = 100
report("inside passSlice")
}
// reports the current memory usage
// don't worry about this code
func report(msg string) {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("[%s]\n", msg)
fmt.Printf("\t> Memory Usage: %v KB\n", m.Alloc/1024)
}
================================================
FILE: 16-slices/exercises/18-internals-slice-header/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"runtime"
"runtime/debug"
"unsafe"
)
const size = 1e7
func main() {
debug.SetGCPercent(-1)
report("initial memory usage")
var array [size]int
report("after declaring an array")
array2 := array
report("after copying the array")
passArray(array)
slice1 := array[:]
slice2 := array[:1e3]
slice3 := array[1e3:1e4]
report("after slicings")
passSlice(slice3)
fmt.Println()
fmt.Printf("Array's size : %d bytes.\n", unsafe.Sizeof(array))
fmt.Printf("Array2's size: %d bytes.\n", unsafe.Sizeof(array2))
fmt.Printf("Slice1's size: %d bytes.\n", unsafe.Sizeof(slice1))
fmt.Printf("Slice2's size: %d bytes.\n", unsafe.Sizeof(slice2))
fmt.Printf("Slice3's size: %d bytes.\n", unsafe.Sizeof(slice3))
}
func passArray(items [size]int) {
items[0] = 100
report("inside passArray")
}
func passSlice(items []int) {
report("inside passSlice")
}
func report(msg string) {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("[%s]\n", msg)
fmt.Printf("\t> Memory Usage: %v KB\n", m.Alloc/1024)
}
================================================
FILE: 16-slices/exercises/19-observe-len-cap/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Observe the length and capacity
//
// Follow the instructions inside the code below to
// gain more intuition about the length and capacity of a slice.
//
// ---------------------------------------------------------
func main() {
// --- #1 ---
// 1. create a new slice named: games
//
// 2. print the length and capacity of the games slice
//
// 3. comment out the games slice
// then declare it as an empty slice
//
// 4. print the length and capacity of the games slice
//
// 5. append the elements: "pacman", "mario", "tetris", "doom"
//
// 6. print the length and capacity of the games slice
//
// 7. comment out everything
//
// 8. declare the games slice again using a slice literal
// (use the same elements from step 5)
// --- #2 ---
// 1. use a loop from 0 to 4 to slice the games slice, element by element.
//
// 2. print its length and capacity along the way (in the loop).
fmt.Println()
// for ... {
// fmt.Printf("games[:%d]'s len: %d cap: %d\n", ...)
// }
// --- #3 ---
// 1. slice the games slice up to zero element
// (save the result to a new slice named: "zero")
//
// 2. print the games and the new slice's len and cap
//
// 3. append a new element to the new slice
//
// 4. print the new slice's lens and caps
//
// 5. repeat the last two steps 5 times (use a loop)
//
// 6. notice the growth of the capacity after the 5th append
//
// Use this slice's elements to append to the new slice:
// []string{"ultima", "dagger", "pong", "coldspot", "zetra"}
fmt.Println()
// zero := ...
// fmt.Printf("games's len: %d cap: %d\n", ...)
// fmt.Printf("zero's len: %d cap: %d\n", ...)
// for ... {
// ...
// fmt.Printf("zero's len: %d cap: %d\n", ...)
// }
// --- #4 ---
// using a range loop, slice the zero slice element by element,
// and print its length and capacity along the way.
//
// observe that, the range loop only loops for the length, not the cap.
fmt.Println()
// for ... {
// s := zero[:n]
// fmt.Printf("zero[:%d]'s len: %d cap: %d\n", ...)
// }
// --- #5 ---
// 1. do the 3rd step above again but this time, start by slicing
// the zero slice up to its capacity (use the cap function).
//
// 2. print the elements of the zero slice in the loop.
fmt.Println()
// zero = ...
// for ... {
// fmt.Printf("zero[:%d]'s len: %d cap: %d - %q\n", ...)
// }
// --- #6 ---
// 1. change the one of the elements of the zero slice
//
// 2. change the same element of the games slice
//
// 3. print the games and the zero slices
//
// 4. observe that they don't have the same backing array
fmt.Println()
// ...
// fmt.Printf("zero : %q\n", zero)
// fmt.Printf("games : %q\n", games)
// --- #7 ---
// try to slice the games slice beyond its capacity
}
================================================
FILE: 16-slices/exercises/19-observe-len-cap/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// --- #1 ---
// var games []string
// fmt.Printf("games's len : %d cap: %d\n", len(games), cap(games))
// games := []string{}
// fmt.Printf("games's len : %d cap: %d\n", len(games), cap(games))
// games = append(games, "pacman", "mario", "tetris", "doom")
// fmt.Printf("games's len : %d cap: %d\n", len(games), cap(games))
games := []string{"pacman", "mario", "tetris", "doom"}
fmt.Printf("games's len : %d cap: %d\n", len(games), cap(games))
// --- #2 ---
fmt.Println()
for i := 0; i <= len(games); i++ {
s := games[:i]
fmt.Printf("games[:%d]'s len: %d cap: %d\n", i, len(s), cap(s))
}
// --- #3 ---
fmt.Println()
zero := games[:0]
fmt.Printf("games's len: %d cap: %d\n", len(games), cap(games))
fmt.Printf("zero's len: %d cap: %d\n", len(zero), cap(zero))
for _, v := range []string{"ultima", "dagger", "pong", "coldspot", "zetra"} {
zero = append(zero, v)
fmt.Printf("zero's len: %d cap: %d\n", len(zero), cap(zero))
}
// --- #4 ---
fmt.Println()
for n := range zero {
s := zero[:n]
fmt.Printf("zero[:%d]'s len: %d cap: %d\n", n, len(s), cap(s))
}
// --- #5 ---
fmt.Println()
zero = zero[:cap(zero)]
for n := range zero {
s := zero[:n]
fmt.Printf("zero[:%d]'s len: %d cap: %d - %q\n", n, len(s), cap(s), s)
}
// --- #6 ---
fmt.Println()
zero[0] = "command & conquer"
games[0] = "red alert"
fmt.Printf("zero : %q\n", zero)
fmt.Printf("games : %q\n", games)
// --- #7 ---
// uncomment and see the error.
// _ = games[:cap(games)+1]
// or:
// _ = games[:5]
}
================================================
FILE: 16-slices/exercises/20-observe-the-cap-growth/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Observe the capacity growth
//
// Write a program that appends elements to a slice
// 10 million times in a loop. Observe how the capacity of
// the slice changes.
//
//
// STEPS
//
// 1. Create a nil slice
//
// 2. Loop 1e7 times
//
// 3. On each iteration: Append an element to the slice
//
// 4. Print the length and capacity of the slice "only"
// when its capacity changes.
//
// BONUS: Print also the growth rate of the capacity.
//
//
// EXPECTED OUTPUT
//
// len:0 cap:0 growth:NaN
// len:1 cap:1 growth:+Inf
// len:2 cap:2 growth:2.00
// ... and so on.
//
// ---------------------------------------------------------
func main() {}
================================================
FILE: 16-slices/exercises/20-observe-the-cap-growth/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
nums []int
oldCap float64
)
// loop 10 million times
for len(nums) < 1e7 {
// get the capacity
c := float64(cap(nums))
// only print when the capacity changes
if c == 0 || c != oldCap {
// print also the growth ratio: c/oldCap
fmt.Printf("len:%-15d cap:%-15g growth:%-15.2f\n",
len(nums), c, c/oldCap)
}
// keep track of the previous capacity
oldCap = c
// append an arbitrary element to the slice
nums = append(nums, 1)
}
}
================================================
FILE: 16-slices/exercises/21-correct-the-lyric/hints.md
================================================
# Hints
You can use the following slice operations to solve the exercise:
+ Prepends "value" to the slice:
```go
slice = append([]string{"value"}, slice...)
```
+ Appends some part (N to M) of the same slice to itself:
```go
slice = append(slice, slice[N:M]...)
```
+ Copies the last part of the slice starting from M to the first part of the slice until N:
```go
slice = append(slice[:N], slice[M:]...)
```
================================================
FILE: 16-slices/exercises/21-correct-the-lyric/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
// ---------------------------------------------------------
// EXERCISE: Correct the lyric
//
// You have a slice that contains the words of Beatles'
// legendary song: Yesterday. However, the order of the
// words are incorrect.
//
// CURRENT OUTPUT
//
// [all my troubles seemed so far away oh I believe in yesterday now it looks as though they are here to stay]
//
// EXPECTED OUTPUT
//
// [yesterday all my troubles seemed so far away now it looks as though they are here to stay oh I believe in yesterday]
//
//
// STEPS
//
// INITIAL SLICE:
// [all my troubles seemed so far away oh I believe in yesterday now it looks as though they are here to stay]
//
//
// 1. Prepend "yesterday" to the `lyric` slice.
//
// RESULT SHOULD BE:
// [yesterday all my troubles seemed so far away oh I believe in yesterday now it looks as though they are here to stay]
//
//
// 2. Put the words to the correct positions in the `lyric` slice.
//
// RESULT SHOULD BE:
// [yesterday all my troubles seemed so far away now it looks as though they are here to stay oh I believe in yesterday]
//
//
// 3. Print the `lyric` slice.
//
//
// BONUS
//
// + Think about when does the append allocate a new backing array.
//
// + Check whether your conclusions are correct.
//
//
// HINTS
//
// If you get stuck, check out the hints.md file.
//
// ---------------------------------------------------------
func main() {
// DON'T TOUCH THIS:
lyric := strings.Fields(`all my troubles seemed so far away oh I believe in yesterday now it looks as though they are here to stay`)
// ADD YOUR CODE BELOW:
// ...
fmt.Printf("%s\n", lyric)
}
================================================
FILE: 16-slices/exercises/21-correct-the-lyric/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
// --- Correct Lyric ---
// yesterday all my troubles seemed so far away
// now it looks as though they are here to stay
// oh I believe in yesterday
lyric := strings.Fields(`all my troubles seemed so far away oh I believe in yesterday now it looks as though they are here to stay`)
// ------------------------------------------------------------------------
// #1: Prepend "yesterday" to `lyric`
// ------------------------------------------------------------------------
//
// --- BEFORE ---
// all my troubles seemed so far away oh I believe in yesterday
//
// --- AFTER ---
// yesterday all my troubles seemed so far away oh I believe in yesterday
//
// (warning: allocates a new backing array)
//
lyric = append([]string{"yesterday"}, lyric...)
// ------------------------------------------------------------------------
// #2: Put the words to the correct positions in the `lyric` slice.
// ------------------------------------------------------------------------
//
// yesterday all my troubles seemed so far away oh I believe in yesterday
// | |
// v v
// index: 8 pos: 13
//
const N, M = 8, 13
// --- BEFORE ---
//
// yesterday all my troubles seemed so far away oh I believe in yesterday now it looks as though they are here to stay
//
// --- AFTER ---
// yesterday all my troubles seemed so far away oh I believe in yesterday now it looks as though they are here to stay oh I believe in yesterday
// ^
//
// |
// +--- duplicate
//
// (warning: allocates a new backing array)
lyric = append(lyric, lyric[N:M]...)
//
// --- BEFORE ---
// yesterday all my troubles seemed so far away oh I believe in yesterday now it looks as though they are here to stay oh I believe in yesterday
//
// --- AFTER ---
// yesterday all my troubles seemed so far away now it looks as though they are here to stay oh I believe in yesterday
//
// (does not allocate a new backing array because cap(lyric[:N]) > M)
//
lyric = append(lyric[:N], lyric[M:]...)
// ------------------------------------------------------------------------
// #3: Print
// ------------------------------------------------------------------------
fmt.Printf("%s\n", lyric)
}
================================================
FILE: 16-slices/exercises/22-adv-ops-practice/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
// ---------------------------------------------------------
// EXERCISE: Practice advanced slice operations
//
// Please follow the directions in the following code.
//
// To see the expected output, please run:
//
// go run solution/main.go
//
// ---------------------------------------------------------
func main() {
// ########################################################
//
// #1: Create a string slice: `names` with a length and
// capacity of 5, and print it.
//
//
// ...
// s.Show("1st step", names)
// ########################################################
//
// #2: Append the following names to the names slice:
//
// "einstein", "tesla", "aristotle"
//
// Print the names slice.
//
// Observe how the slice and its backing array change.
//
//
// ...
// s.Show("2nd step", names)
// ########################################################
//
// #3: Overwrite the name slice by creating a new slice
// using make().
//
// Adjust the make() function so that it creates a
// slice with capacity of 5, and puts the slice pointer
// to the first index.
//
// Then append the following names to the slice:
//
// "einstein", "tesla", "aristotle"
//
// Expected output:
// ["einstein", "tesla", "aristotle" "" ""]
//
//
// ...
// s.Show("3rd step", names)
// ########################################################
//
// #4: Copy only the first two elements of the following
// array to the last two elements of the `names` slice.
//
// Print the names slice, you should see 5 elements.
// So, do not forget extending the slice.
//
// Observe how its backing array stays the same.
//
//
// Array (uncomment):
// moreNames := [...]string{"plato", "khayyam", "ptolemy"}
//
// ...
//
// s.Show("4th step", names)
// ########################################################
//
// #5: Only copy the last 3 elements of the `names` slice
// to a new slice: `clone`.
//
// Append the first two elements of the `names` to the
// `clone`.
//
// Ensure that after appending no new backing array
// allocations occur for the `clone` slice.
//
// Print the clone slice before and after the append.
//
//
// ...
// s.Show("5th step (before append)", clone)
//
// ...
// s.Show("5th step (after append)", clone)
// ########################################################
//
// #6: Slice the `clone` slice between 2nd and 4th (inclusive)
// elements into a new slice: `sliced`.
//
// Append "hypatia" to the `sliced`.
//
// Ensure that new backing array allocation "occurs".
//
// Change the 3rd element of the `clone` slice
// to "elder".
//
// Doing so should not change any elements of
// the `sliced` slice.
//
// Print the `clone` and `sliced` slices.
//
//
// ...
// s.Show("6th step", clone, sliced)
}
//
// Don't mind about this function.
//
// For printing the slices: You can either use the
// prettyslice package or `fmt.Printf`.
//
func init() {
s.PrintBacking = true // prints the backing array
s.MaxPerLine = 10 // prints 10 slice elements per line
s.Width = 60 // prints 60 character per line
}
================================================
FILE: 16-slices/exercises/22-adv-ops-practice/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
s "github.com/inancgumus/prettyslice"
)
func main() {
// ########################################################
//
// #1: Create a string slice: `names` with a length and
// capacity of 5, and print it.
//
names := make([]string, 5)
s.Show("1st step", names)
// ########################################################
//
// #2: Append the following names to the names slice:
//
// "einstein", "tesla", "aristotle"
//
// Print the names slice.
//
// Observe how the slice and its backing array change.
//
// Expected output:
// ["" "" "" "" "" "einstein", "tesla", "aristotle"]
//
names = append(names, "einstein", "tesla", "aristotle")
s.Show("2nd step", names)
// ########################################################
//
// #3: Overwrite the name slice by creating a new slice
// using make().
//
// Adjust the make() function so that it creates a
// slice with capacity of 5, and puts the slice pointer
// to the first index.
//
// Then append the following names to the slice:
//
// "einstein", "tesla", "aristotle"
//
// Expected output:
// ["einstein", "tesla", "aristotle" "" ""]
//
// So: Overwrite and print the names slice.
//
names = make([]string, 0, 5)
names = append(names, "einstein", "tesla", "aristotle")
s.Show("3rd step", names)
// ########################################################
//
// #4: Copy only the first two elements of the following
// array to the last two elements of the `names` slice.
//
// Print the names slice, you should see 5 elements.
// So, do not forget extending the slice.
//
// Observe how its backing array stays the same.
//
moreNames := [...]string{"plato", "khayyam", "ptolemy"}
copy(names[3:5], moreNames[:2])
names = names[:cap(names)]
s.Show("4th step", names)
// ########################################################
//
// #5: Only copy the last 3 elements of the `names` slice
// to a new slice: `clone`.
//
// Append the first two elements of the `names` to the
// `clone`.
//
// Ensure that after appending no new backing array
// allocations occur for the `clone` slice.
//
// Print the clone slice before and after the append.
//
clone := make([]string, 3, 5)
copy(clone, names[len(names)-3:])
s.Show("5th step (before append)", clone)
clone = append(clone, names[:2]...)
s.Show("5th step (after append)", clone)
// ########################################################
//
// #6: Slice the `clone` slice between 2nd and 4th (inclusive)
// elements into a new slice: `sliced`.
//
// Append "hypatia" to the `sliced`.
//
// Ensure that new backing array allocation "occurs".
//
// Change the 3rd element of the `clone` slice
// to "elder".
//
// Doing so should not change any elements of
// the `sliced` slice.
//
// Print the `clone` and `sliced` slices.
//
//
sliced := clone[1:4:4]
sliced = append(sliced, "hypatia")
clone[2] = "elder"
s.Show("6th step", clone, sliced)
}
//
// Don't mind about this function.
//
// For printing the slices: You can either use the
// prettyslice package or `fmt.Printf`.
//
func init() {
s.PrintBacking = true // prints the backing array
s.MaxPerLine = 10 // prints 10 slice elements per line
s.Width = 60 // prints 60 character per line
}
================================================
FILE: 16-slices/exercises/23-limit-the-backing-array-sharing/api/api.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package api
var temps = []int{5, 10, 3, 25, 45, 80, 90}
// Read returns a slice of elements from the temps slice.
func Read(start, stop int) []int {
// ----------------------------------------
// RESTRICTIONS — ONLY ADD YOUR CODE IN THIS AREA
portion := temps[start:stop]
// RESTRICTIONS — ONLY ADD YOUR CODE IN THIS AREA
// ----------------------------------------
return portion
}
// All returns the temps slice
func All() []int {
return temps
}
================================================
FILE: 16-slices/exercises/23-limit-the-backing-array-sharing/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"github.com/inancgumus/learngo/16-slices/exercises/23-limit-the-backing-array-sharing/api"
)
// ---------------------------------------------------------
// EXERCISE: Limit the backing array sharing
//
// GOAL
//
// Limit the capacity of the slice that is returned
// from the `Read` function. Read on for more details.
//
//
// BEFORE YOU START
//
// In this exercise: API means the api package. It's in the
// api folder. You need to change the code in the `api/api.go`
// to solve this exercise, and you need import the api
// package.
//
//
// WHAT IS THE PROBLEM?
//
// `Read` function of the api package returns a portion of
// its `temps` slice. Below, `main()` saves it to the
// `received` slice.
//
// `main()` appends to the `received` slice but doing so
// also changes the backing array of the `temps` slice.
// We don't want that.
//
// `main()` can change the part of the `temps` slice
// that is returned from the `Read()`, but it shouldn't
// be able to change the elements in the rest of the
// `temps`.
//
//
// WHAT YOU NEED TO DO?
//
// So you need to limit the capacity of the returned
// slice somehow. Remember: `received` and `temps`
// share the same backing array. So, appending to it
// can overwrite the same backing array.
//
//
// CURRENT
//
// | |
// v v
// api.temps : [5 10 3 1 3 80 90]
// main.received : [5 10 3 1 3]
// ^ ^ append changes the `temps`
// slice's backing array.
//
//
//
// EXPECTED
//
// The corrected api package does not allow the `main()` to
// change unreturned portion of the temps slice's backing array.
// | |
// v v
// api.temps : [5 10 3 25 45 80 90]
// main.received : [5 10 3 1 3]
//
// ---------------------------------------------------------
func main() {
// DO NOT CHANGE ANYTHING IN THIS CODE.
// get the first three elements from api.temps
received := api.Read(0, 3)
// append changes the api package's temps slice's
// backing array as well.
received = append(received, []int{1, 3}...)
fmt.Println("api.temps :", api.All())
fmt.Println("main.received :", received)
}
================================================
FILE: 16-slices/exercises/23-limit-the-backing-array-sharing/solution/api/api.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package api
var temps = []int{5, 10, 3, 25, 45, 80, 90}
// Read returns a slice of elements from the temps slice.
func Read(start, stop int) []int {
//
// The third index prevents the `main()` from
// overwriting the original temps slice's
// backing array. It limits the capacity of the
// returned slice. See the full slice expressions
// lecture for more details.
//
portion := temps[start:stop:stop]
return portion
}
// All returns the temps slice
func All() []int {
return temps
}
================================================
FILE: 16-slices/exercises/23-limit-the-backing-array-sharing/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"github.com/inancgumus/learngo/16-slices/exercises/23-limit-the-backing-array-sharing/solution/api"
)
func main() {
received := api.Read(0, 3)
received = append(received, []int{1, 3}...)
fmt.Println("api.temps :", api.All())
fmt.Println("main.received :", received)
}
================================================
FILE: 16-slices/exercises/24-fix-the-memory-leak/api/api.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package api
import (
"fmt"
"math/rand"
"runtime"
)
// DO NOT TOUCH THIS FILE BUT YOU CAN READ IT
// Read returns a huge slice (allocates ~65 MB of memory)
func Read() []int {
// 2 << 22 means 2^(22 + 1)
// See this: https://en.wikipedia.org/wiki/Arithmetic_shift
// Perm function returns a slice with random integers in it.
// Here it returns a slice with random integers that contains
// 8,388,608 elements. One int value is 8 bytes.
// So: 8,388,608 * 8 = ~65MB
return rand.Perm(2 << 22)
}
// Report cleans the memory and prints the current memory usage
// Don't worry about this code. You don't need to understand it.
//
// However, if you're curious, read on.
//
// The following code runs the garbage collector to clean
// up the allocated resources, and then it reads the current
// memory statistics into the m variable.
func Report() {
var m runtime.MemStats
runtime.GC()
runtime.ReadMemStats(&m)
fmt.Printf(" > Memory Usage: %v KB\n", m.Alloc/1024)
}
================================================
FILE: 16-slices/exercises/24-fix-the-memory-leak/hints.md
================================================
# Hints
+ `millions` slice's backing array uses 65 MB of memory.
+ `make` a new slice with 10 elements with a new backing array.
+ `copy` the last 10 elements of the `millions` slice to the new slice.
+ So you will have slice with a new backing array only with 10 elements.
+ Then overwrite the `millions` slice by simply `assigning` `last10` slice to it.
+ **Remember:** slice ~= pointer to a backing array.
If you overwrite the slice, it will lose that
pointer. So Go can collect the unused memory.
================================================
FILE: 16-slices/exercises/24-fix-the-memory-leak/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io/ioutil"
"github.com/inancgumus/learngo/16-slices/exercises/24-fix-the-memory-leak/api"
)
// ---------------------------------------------------------
// EXERCISE: Fix the memory leak
//
// WARNING
//
// This is a very difficult exercise. You need to
// do some research on your own to solve it. Please don't
// get discouraged if you can't solve it yet.
//
//
// GOAL
//
// In this exercise, your goal is to reduce the memory
// usage. To do that, you need to find and fix the memory
// leak within `main()`.
//
//
// PROBLEM
//
// `main()` calls `api.Report()` that reports the current
// memory usage.
//
// After that, `main()` calls `api.Read()` that returns
// a slice with 10 millions of elements. But you only need
// the last 10 elements of the returned slice.
//
//
// WHAT YOU NEED TO DO
//
// You only need to change the code in `main()`. Please
// do not touch the code in `api/api.go`.
//
//
// CURRENT OUTPUT
//
// > Memory Usage: 113 KB
//
// Last 10 elements: [...]
//
// > Memory Usage: 65651 KB
//
// + Before `api.Read()` call: It uses 113 KB of memory.
//
// + After `api.Read()` call : It uses 65 MB of memory.
//
// + This means that, `main()` never releases the memory.
// This is the leak.
//
// + Your goal is to release the unused memory. Remember,
// you only need 10 elements but in the current code
// below you have a slice with 10 millions of elements.
//
//
// EXPECTED OUTPUT
//
// > Memory Usage: 116 KB
//
// Last 10 elements: [...]
//
// > Memory Usage: 118 KB
//
// + In the expected output, `main()` releases the memory.
//
// It no longer uses 65 MB of memory. Instead, it only
// uses 118 KB of memory. That's why the second
// `api.Report()` call reports 118 KB.
//
//
// ADDITIONAL NOTE
//
// Memory leak means: Your program is using unnecessary
// computer memory. It doesn't release memory that is
// no longer needed.
//
// See this for more information:
// https://en.wikipedia.org/wiki/Memory_leak
//
//
// HINTS
//
// Check out `hints.md` file if you get stuck.
//
// ---------------------------------------------------------
func main() {
// reports the initial memory usage
api.Report()
// returns a slice with 10 million elements.
// it allocates 65 MB of memory space.
millions := api.Read()
// -----------------------------------------------------
// ✪ ONLY CHANGE THE CODE IN THIS AREA ✪
last10 := millions[len(millions)-10:]
fmt.Printf("\nLast 10 elements: %d\n\n", last10)
// ✪ ONLY CHANGE THE CODE IN THIS AREA ✪
// -----------------------------------------------------
api.Report()
// don't worry about this code.
fmt.Fprintln(ioutil.Discard, millions[0])
}
================================================
FILE: 16-slices/exercises/24-fix-the-memory-leak/solution/api/api.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package api
import (
"fmt"
"math/rand"
"runtime"
)
// DO NOT TOUCH THIS FILE BUT YOU CAN READ IT
// Read returns a huge slice (allocates ~65 MB of memory)
func Read() []int {
// 2 << 22 means 2^(22 + 1)
// See this: https://en.wikipedia.org/wiki/Arithmetic_shift
// Perm function returns a slice with random integers in it.
// Here it returns a slice with random integers that contains
// 8,388,608 elements. One int value is 8 bytes.
// So: 8,388,608 * 8 = ~65MB
return rand.Perm(2 << 22)
}
// Report cleans the memory and prints the current memory usage
// Don't worry about this code. You don't need to understand it.
//
// However, if you're curious, read on.
//
// The following code runs the garbage collector to clean
// up the allocated resources, and then it reads the current
// memory statistics into the m variable.
func Report() {
var m runtime.MemStats
runtime.GC()
runtime.ReadMemStats(&m)
fmt.Printf(" > Memory Usage: %v KB\n", m.Alloc/1024)
}
================================================
FILE: 16-slices/exercises/24-fix-the-memory-leak/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io/ioutil"
"github.com/inancgumus/learngo/16-slices/exercises/24-fix-the-memory-leak/solution/api"
)
func main() {
// reports the initial memory usage
api.Report()
// returns a slice with 10 million elements.
// it allocates 65 MB of memory space.
millions := api.Read()
// ------------------------------------------------------
// SOLUTION #1:
// Copy the last 10 elements of the returned slice
// to a new slice. This will create a new backing array
// only with 10 elements.
last10 := make([]int, 10)
copy(last10, millions[len(millions)-10:])
// Make the millions slice lose reference to its backing array
// so that its backing array can be cleaned up from memory.
millions = last10
// SOLUTION #2:
// Similar to the 1st solution. It does the same thing.
// But this code is more concise. Use this one.
// millions = append([]int(nil), millions[len(millions)-10:]...)
fmt.Printf("\nLast 10 elements: %d\n\n", last10)
// ------------------------------------------------------
api.Report()
// don't worry about this code yet.
fmt.Fprintln(ioutil.Discard, millions[0])
}
================================================
FILE: 16-slices/exercises/25-add-lines/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
s "github.com/inancgumus/prettyslice"
)
// ---------------------------------------------------------
// EXERCISE: Add a newline after each sentence
//
// You have a slice that contains Beatles' awesome song:
// Yesterday. You want to add newlines after each sentence.
//
// So, create a new slice and copy every words into it. Lastly,
// after each sentence, add a newline character ('\n').
//
//
// ORIGINAL SLICE:
//
// [yesterday all my troubles seemed so far away now it looks as though they are here to stay oh I believe in yesterday]
//
// EXPECTED SLICE (NEW):
//
// [yesterday all my troubles seemed so far \n away now it looks as though they are here to stay \n oh I believe in yesterday \n]
//
//
// CURRENT OUTPUT
//
// yesterday all my troubles seemed so far away now it looks as though they are here to stay oh I believe in yesterday
//
// EXPECTED OUTPUT
//
// yesterday all my troubles seemed so far away
// now it looks as though they are here to stay
// oh I believe in yesterday
//
//
// RESTRICTIONS
//
// + Don't use `append()`, use `copy()` instead.
//
// + Don't cheat like this:
//
// fmt.Println(lyric[:8])
// fmt.Println(lyric[8:18])
// fmt.Println(lyric[18:23])
//
// + Create a new slice that contains the sentences
// with line endings.
//
//
// NOTE
//
// If the program does not work, please update your
// local copy of the prettyslice package:
//
// go get -u github.com/inancgumus/prettyslice
//
//
// ---------------------------------------------------------
func main() {
// You need to add a newline after each sentence in another slice.
// Don't touch the following code.
lyric := strings.Fields(`yesterday all my troubles seemed so far away now it looks as though they are here to stay oh I believe in yesterday`)
// ===================================
//
// ~~~ CHANGE THIS CODE ~~~
//
fix := lyric
//
// ===================================
// Currently, it prints every sentence on the same line.
// Don't touch the following code.
s.Show("fix slice", fix)
for _, w := range fix {
fmt.Print(w)
if w != "\n" {
fmt.Print(" ")
}
}
}
func init() {
//
// YOU DON'T NEED TO TOUCH THIS
//
// This initializes some options for the prettyslice package.
// You can change the options if you want.
//
// This code runs before the main function above.
//
// s.Colors(false) // if your editor is light background color then enable this
//
s.PrintBacking = true // prints the backing arrays
s.MaxPerLine = 5 // prints max 15 elements per line
s.SpaceCharacter = '⏎' // print this instead of printing a newline (for debugging)
}
================================================
FILE: 16-slices/exercises/25-add-lines/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
s "github.com/inancgumus/prettyslice"
)
func main() {
lyric := strings.Fields(`yesterday all my troubles seemed so far away now it looks as though they are here to stay oh I believe in yesterday`)
// `+3` because we're going to add 3 newline characters to the fix slice.
fix := make([]string, len(lyric)+3)
//
// USE A SLICE TO STORE WHERE EACH SENTENCE ENDS
//
// + The first sentence has 8 words so its cutting index is 8.
//
// yesterday all my troubles seemed so far away now it looks as though they are here to stay
// |
// v
// cutting index: 8
//
//
// + The second sentence has 10 words so its cutting index is 10.
//
// now it looks as though they are here to stay oh I believe in yesterday
// |
// v
// cutting index: 10
//
//
// + The last sentence has 5 words so its cutting index is 5.
//
// oh I believe in yesterday
// |
// v
// cutting index: 5
//
cutpoints := []int{8, 10, 5}
//
// `n` tracks how much we've moved inside the `lyric` slice.
//
// `i` tracks the sentence that we're on.
//
for i, n := 0, 0; n < len(lyric); i++ {
//
// copy to `fix` from the `lyric`
//
// destination:
// fix[n+i] because we don't want to delete the previous copy.
// it moves sentence by sentence, using the cutpoints.
//
// source:
// lyric[n:n+cutpoints[i]] because we want copy the next sentence
// beginning from the number of the last copied elements to the
// n+next cutpoint (the next sentence).
//
n += copy(fix[n+i:], lyric[n:n+cutpoints[i]])
//
// add a newline after each sentence.
//
// notice that the '\n' position slides as we move over.
// that's why it's: `n+i`.
//
fix[n+i] = "\n"
// uncomment to see how the fix slice changes.
// s.Show("fix slice", fix)
}
s.Show("fix slice", fix)
// print the sentences
for _, w := range fix {
fmt.Print(w)
if w != "\n" {
fmt.Print(" ")
}
}
}
func init() {
//
// YOU DON'T NEED TO TOUCH THIS
//
// This initializes some options for the prettyslice package.
// You can change the options if you want.
//
// This code runs before the main function above.
//
// s.Colors(false) // if your editor is light background color then enable this
s.PrintBacking = true // prints the backing arrays
s.MaxPerLine = 5 // prints max 15 elements per line
s.SpaceCharacter = '⏎' // print this instead of printing a newline (for debugging)
}
================================================
FILE: 16-slices/exercises/26-print-daily-requests/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
// ---------------------------------------------------------
// EXERCISE: Print daily requests
//
// You've got request logs of a web server. The log data
// contains 8-hourly totals per each day. It is stored
// in the `reqs` slice.
//
// Find and print the total requests per day, as well as
// the grand total.
//
// See the `reqs` slice and the steps in the code below.
//
//
// RESTRICTIONS
//
// 1. You need to produce the daily slice, don't just loop
// and print the element totals directly. The goal is
// gaining more experience in slice operations.
//
// 2. Your code should work even if you add to or remove the
// existing elements from the `reqs` slice.
//
// For example, after solving the exercise, try it with
// this new data:
//
// reqs := []int{
// 500, 600, 250,
// 200, 400, 50,
// 900, 800, 600,
// 750, 250, 100,
// 150, 654, 235,
// 320, 534, 765,
// 121, 876, 285,
// 543, 642,
// // the last element is missing (your code should be able to handle this)
// // that is why you shouldn't calculate the `size` below manually.
// }
//
// The grand total of the new data should be 10525.
//
//
// EXPECTED OUTPUT
//
// Please run `solution/main.go` to see the expected
// output.
//
// go run solution/main.go
//
// ---------------------------------------------------------
func main() {
// There are 3 request totals per day (8-hourly)
const N = 3
// DAILY REQUESTS DATA (8-HOURLY TOTALS PER DAY)
reqs := []int{
500, 600, 250, // 1st day: 1350 requests
200, 400, 50, // 2nd day: 650 requests
900, 800, 600, // 3rd day: 2300 requests
750, 250, 100, // 4th day: 1100 requests
// grand total: 5400 requests
}
// ================================================
// #1: Make a new slice with the exact size needed.
_ = reqs // remove this when you start
size := 0 // you need to find the size.
daily := make([][]int, 0, size)
// ================================================
// ================================================
// #2: Group the `reqs` per day into the slice: `daily`.
//
// So the daily will be:
// [
// [500, 600, 250]
// [200, 400, 50]
// [900, 800, 600]
// [750, 250, 100]
// ]
_ = daily // remove this when you start
// ================================================
// #3: Print the results
// Print a header
fmt.Printf("%-10s%-10s\n", "Day", "Requests")
fmt.Println(strings.Repeat("=", 20))
// Loop over the daily slice and its inner slices to find
// the daily totals and the grand total.
// ...
// ================================================
}
================================================
FILE: 16-slices/exercises/26-print-daily-requests/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
// There are 3 request totals per day
const N = 3
// DAILY REQUESTS DATA (PER 8-HOUR)
reqs := []int{
500, 600, 250, // 1st day: 1350 requests
200, 400, 50, // 2nd day: 650 requests
900, 800, 600, // 3rd day: 2300 requests
750, 250, 100, // 4th day: 1100 requests
// grand total: 5400 requests
}
// ALSO TRY IT WITH THIS DATA:
// reqs = []int{
// 500, 600, 250,
// 200, 400, 50,
// 900, 800, 600,
// 750, 250, 100,
// 150, 654, 235,
// 320, 534, 765,
// 121, 876, 285,
// 543, 642,
// }
// ================================================
// Allocate a slice efficiently with the exact size needed.
//
// Find the `size` automatically using the `reqs` slice.
// Do not type it manually.
//
l := len(reqs)
size := l / N
if l%N != 0 {
size++
}
daily := make([][]int, 0, size)
//
// ================================================
// ================================================
// Group the `reqs` per day into the slice: `daily`.
//
// So the daily will be:
// [
// [500, 600, 250]
// [200, 400, 50]
// [900, 800, 600]
// [750, 250, 100]
// ]
//
for N <= len(reqs) {
daily = append(daily, reqs[:N]) // append the daily requests
reqs = reqs[N:] // move the slice pointer for the next day
}
// add the residual data
if len(reqs) > 0 {
daily = append(daily, reqs)
}
// ================================================
// ================================================
// Print the header
fmt.Printf("%-10s%-10s\n", "Day", "Requests")
fmt.Println(strings.Repeat("=", 20))
// Print the data per day along with the totals
var grand int
for i, day := range daily {
var sum int
for _, req := range day {
sum += req
fmt.Printf("%-10d%-10d\n", i+1, req)
}
fmt.Printf("%9s %-10d\n\n", "TOTAL:", sum)
grand += sum
}
fmt.Printf("%9s %-10d\n", "GRAND:", grand)
// ================================================
}
================================================
FILE: 16-slices/exercises/README.md
================================================
# Slice Exercises
## Exercises Level I - Basics — Warm-Up
Let's reinforce your basic knowledge of slices.
1. **[Declare nil slices](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/01-declare-nil)**
2. **[Assign empty slices](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/02-empty)**
3. **[Assign slice literals](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/03-slice-literal)**
4. **[Declare the arrays as slices](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/04-declare-arrays-as-slices)**
5. **[Fix the Problems](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/05-fix-the-problems)**
6. **[Compare the slices](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/06-compare-the-slices)**
---
## Exercises Level II - Appending
Discover the power of the append function.
1. **[Append #1 — Append and compare byte slices](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/07-append)**
2. **[Append #2 — Append to a nil slice](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/08-append-2)**
3. **[Append #3 — Fix the problems](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/09-append-3-fix)**
4. **[Append and Sort Numbers](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/10-append-sort-nums)**
5. **[Housing Prices](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/11-housing-prices)**
6. **[Housing Prices and Averages](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/12-housing-prices-averages)**
---
## Exercises Level III - Slicing
Discover the power of slicing.
1. **[Slice the numbers](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/13-slicing-basics)**
2. **[Slicing by arguments](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/14-slicing-by-args)**
3. **[Slicing the Housing Prices](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/15-slicing-housing-prices)**
---
## Exercises Level IV - Internals
Peek into the internals of the slices and gain more insight. This is necessary for complete command of the slices.
1. **[Fix the backing array problems](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/16-internals-backing-array-fix)**
2. **[Sort the backing array](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/17-internals-backing-array-sort)**
3. **[Observe the memory allocations](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/18-internals-slice-header)**
4. **[Observe the length and capacity](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/19-observe-len-cap)**
5. **[Observe the capacity growth](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/20-observe-the-cap-growth)**
6. **[Correct the lyric](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/21-correct-the-lyric)**
---
## Exercises Level V - Advanced Operations
Commonly used and more advanced operations are available to slices. Now, it's time to test yourself and fix some common problems.
★ WARNING ★
Please update your local copy of the prettyslice package for some examples to work. [Please find the intructions how to do so here](../README.md).
1. **[Practice Advanced Slice Operations](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/22-adv-ops-practice)**
Let's warm you up for the advanced slice operations, and reinforce your neurons.
2. **[Limit the backing array sharing](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/23-limit-the-backing-array-sharing)**
Your package needs to control the slices that it shares with the outside world.
3. **[Fix the Memory Leak](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/24-fix-the-memory-leak)**
A slice retrieved from a package causes a memory leak in your program. You need to fix it.
4. **[Add a newline after each sentence](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/25-add-lines)**
Use the power of the `copy()` function and add newlines into a new buffer from a string slice. This exercise is more tricky than you might think.
5. **[Print Daily Requests](https://github.com/inancgumus/learngo/tree/master/16-slices/exercises/26-print-daily-requests)**
Group the web request logs into a multi-dimensional slice. Allocate a slice with the exact size needed by doing some wizardary calculations. And lastly, pretty print the result.
================================================
FILE: 16-slices/questions/1-slices-vs-arrays.md
================================================
# Slices vs Arrays Quiz
## Why you want to use a slice instead of an array?
1. I like arrays more
2. I want to create a dynamic collection, so I need an array
3. A slice's length is dynamic, so I can create dynamic collections *CORRECT*
## Where does the length of a slice belong to?
1. Compile-Time
2. Runtime *CORRECT*
3. Walk-Time
4. Sleep-Time
> **2:** A slice's length is not a part of its type. So its length can change at runtime.
## Which function call below is correct?
```go
// Let's say there's a function like this.
func sort(nums []int) {
// ...
}
```
1. sort([...]int{3, 1, 6})
2. sort([]int32{3, 1, 6})
3. sort([]int{3, 1, 6}) *CORRECT*
> **1:** You can't call the sort function using an array. It expects an int slice.
>
> **2:** You can't call the sort function using an int32 slice. It expects an int slice.
>
> **3:** That's right! You can pass an int slice to the sort function.
## What is the zero value of this slice?
```go
var tasks []string
```
1. 0
2. 1
3. nil *CORRECT*
4. unknown
> **3:** This is a nil slice. Unlike an array, a slice's zero value is nil.
## What does this code print?
```go
var tasks []string
fmt.Println(len(tasks))
```
1. 0 *CORRECT*
2. 1
3. nil
4. It doesn't work.
> **1:** Yes, you can use the len function on a nil slice. It returns 0 because the slice doesn't contain any elements yet.
## What does this code print?
```go
var tasks []string
fmt.Println(tasks[0])
```
1. 0
2. 1
3. nil
4. It doesn't work. *CORRECT*
> **4:** You can't get an element that does not exist. A nil slice does not contain any elements.
## Which declaration below is a correct slice declaration?
1. [...]int{}
2. [2]string{"hello", "world"}
3. []string{"hello", "world"} *CORRECT*
4. string[2]{"hello", world"}
## This code doesn't work, why?
```go
colors := []string{"red", "blue", "green"}
tones := []string{"dark", "light"}
if colors == tones {
// ...
}
```
1. The slices have different lengths
2. If statement doesn't contain any statements
3. Slices cannot be compared *CORRECT*
> **3:** That's right! A slice value can only be compared to a nil value.
## What is the length of this slice?
```go
[]uint64{}
```
1. 64
2. 1
3. 0 *CORRECT*
4. Error
> **3:** That's right. This is an empty slice, it doesn't contain any elements.
## What is the length of this slice?
```go
[]string{"I'm", "going", "to", "stay", "\"here\""}
```
1. 0
2. 1
3. 2
4. 3
5. 4
6. 5 *CORRECT*
================================================
FILE: 16-slices/questions/2-appending.md
================================================
# Appending Quiz
## How does the append function work?
1. It appends new elements to the given slice on the fly and returns a new slice, normally, it doesn't change the given slice *CORRECT*
2. It appends new elements to the given slice and returns the existing slice
3. It appends new elements to the given slice and returns a new slice, it also changes the given slice
> **1:** Yes, the append function doesn't change the given slice unless you overwrite the result of the append function back to the original slice. Most of the times, this is true.
>
> **2:** It doesn't return the existing slice, it returns a new slice. That's why you usually save the result of the append back to the original slice.
>
> **3:** It doesn't change the given slice, it creates and returns a new slice. Most of the times, this is true.
## When you call the append function, where does it append the new elements?
1. It appends them at the beginning of the given slice
2. It appends them at the middle of the given slice
3. It appends them after the length of the given slice *CORRECT*
> **3:** Yes! The append function appends the new elements by looking at the length of the given slice and then returns a new slice with the newly appended elements.
## What's the problem with the following code?
```go
nums := []int{9, 7, 5}
append(nums, []int{2, 4, 6}...)
fmt.Println(nums[3])
```
1. It can't append to an int slice
2. It can't append a slice to another slice
3. It tries to get an element that doesn't exist yet *CORRECT*
> **3:** That's right. The append function returns a new slice with the newly added elements. But here, the code doesn't save the result of the append, so the nums slice only has 3 elements. So, `nums[3]` is invalid, because there are only 3 elements in the nums slice.
## What does this program print?
```go
nums := []int{9, 7, 5}
evens := append(nums, []int{2, 4, 6}...)
fmt.Println(nums, evens)
```
1. [9 7 5] [2 4 6]
2. [9 7 5] [9 7 5 2 4 6] *CORRECT*
3. [9 7 5 2 4 6] [2 4 6]
4. [9 7 5 2 4 6] [9 7 5 2 4 6]
> **2:** It appends the new elements to the nums slice but it saves the returned slice to the evens slice. So, the nums slice doesn't change. That's why, it prints the original elements from the nums slice first, then it prints the evens slice with the newly added elements.
>
> **3, 4:** It doesn't save the result of the append call back into the nums slice, so the nums slice doesn't contain the new elements.
## What does this program print?
```go
nums := []int{9, 7, 5}
nums = append(nums, 2, 4, 6)
fmt.Println(nums)
```
1. [9 7 5 2 4 6] *CORRECT*
2. [9 7 5]
3. [2 4 6]
4. [2 4 6 9 7 5]
> **1:** It overwrites the nums slice with the new slice that is returned from the append function. So the nums slice has got the newly appended elements.
================================================
FILE: 16-slices/questions/3-slicing.md
================================================
# Slicing Quiz
## What does this code print?
```go
nums := []int{9, 7, 5}
nums = append(nums, 2, 4, 6)
fmt.Println(nums[2:4])
```
1. [9 7 5 2 4 6]
2. [5 2] *CORRECT*
3. [4 6]
4. [7 2]
5. [9 7]
> **2:** nums is [9 7 5 2 4 6]. So, nums[2:4] is [5 2]. Remember, in nums[2:4] -> 2 is the starting index, so nums[2] is 5; And 4 is the stopping position, so nums[4-1] is 2 (-1 because the stopping position is the element position). So, nums[2:4] returns a new slice that contains the elements at the middle of the nums slice.
## What does this code print?
```go
nums := []int{9, 7, 5}
nums = append(nums, 2, 4, 6)
fmt.Println(nums[:2])
```
1. [9 7 5 2 4 6]
2. [5 2]
3. [4 6]
4. [7 2]
5. [9 7] *CORRECT*
> **5:** nums is [9 7 5 2 4 6]. So, nums[:2] is nums[0:2] which in turn returns [9 7].
## What does this code print?
```go
nums := []int{9, 7, 5}
nums = append(nums, 2, 4, 6)
fmt.Println(nums[len(nums)-2:])
```
1. [9 7 5 2 4 6]
2. [5 2]
3. [4 6] *CORRECT*
4. [7 2]
5. [9 7]
> **3:** nums is [9 7 5 2 4 6]. So, nums[len(nums)-2:] is nums[4:6] (len(nums) is 6) which in turn returns [4 6].
## What does this code print?
```go
names := []string{"einstein", "rosen", "newton"}
names = names[:]
fmt.Println(names[:1])
```
1. [einstein rosen newton]
2. [einstein rosen]
3. [einstein] *CORRECT*
4. []
> **3:** names[:] is names[0:3] -> [einstein rosen newton]. names[:1] is names[0:1] -> [einstein].
## What is the type of the marked expression below?
```go
names := []string{"einstein", "rosen", "newton"}
names[2:3] // <- marked
```
1. []string *CORRECT*
2. string
3. names
4. []int
> **1:** Yes! A slicing expression returns a slice.
>
> **2:** Remember, a slicing expression returns a slice. Did I give you the answer? Oops.
## What is the type of the marked expression below?
```go
names := []string{"einstein", "rosen", "newton"}
names[2] // <- marked
```
1. []string
2. string *CORRECT*
3. names
4. []int
> **1:** Remember, an index expression returns an element value, not a slice.
>
> **2:** Yep! An index expression returns an element value. The element type of the []string slice is string, so the returned value is a string value.
## Which index expression returns the "rosen" element?
```go
names := []string{"einstein", "rosen", "newton"}
names = names[1:len(names) - 1]
```
1. names[0] *CORRECT*
2. names[1]
3. names[2]
> **1:** That's right: names2 is ["rosen"] after the slicing.
>
> **2:** That's not right. Remember, indexes are relative to a slice. names is ["einstein" "rosen" "newton"] but names[1:len(names)-1] is ["rosen"]. So, names2[1] is an error, it's because, the length of the last slice is 1.
## What does this code print?
```go
names := []string{"einstein", "rosen", "newton"}
names = names[1:]
names = names[1:]
fmt.Println(names)
```
1. [einstein rosen newton]
2. [rosen newton]
3. [newton] *CORRECT*
4. []
> **3:** Remember, slicing returns a new slice. Here, each `names = names[1:]` statement overwrites the names slice with the newly returned slice from the slicing. At first, the names was [einstein rosen newton]. After the first slicing, the names becomes [rosen newton]. After the second slicing, names becomes [newton]. See this for the complete explanation: https://play.golang.org/p/EsEHrSeByFR
## What does this code print?
```go
i := 2
s := fmt.Sprintf("i = %d * %d = %d", i, i, i*i)
fmt.Print(s)
```
1. i = i * i = i*i
2. i = %d * %d = %d
3. i = 2 * 2 = 2
4. i = 2 * 2 = 4 *CORRECT*
> **4:** Awesome! Sprintf works just like Printf. Instead of printing the result to standard out (usually to command-line prompt), it returns a string value.
================================================
FILE: 16-slices/questions/4-backing-array.md
================================================
# Backing Array Quiz
## Where does a slice store its elements?
1. In the slice value
2. In a global backing array that is shared by all the slices
3. In a backing array that is specific to a slice
4. In a backing array that the slice references *CORRECT*
> **1:** A slice value doesn't store any elements. It's just a simple data structure.
>
> **2:** There is not a global backing array.
>
> **3:** A backing array can be shared among slices. It may not be specific to a slice.
>
> **4:** Yep! A slice stores its elements in a backing that the slice references (or points to).
>
## When you slice a slice, what value does it return?
```go
// example:
s := []string{"I'm", "a", "slice"}
s[2:] // <-- slicing
```
1. It returns a new slice value with a new backing array
2. It returns the existing slice value with a new backing array
3. It returns a new slice value with the same backing array *CORRECT*
> **3:** Yes! Slicing returns a new slice that references to some segment of the same backing array.
## Why are slicing and indexing a slice efficient?
1. Slices are fast
2. Backing arrays are contiguous in memory *CORRECT*
3. Go uses clever algorithms
> **2:** Yes. A slice's backing array is contiguous in memory. So, accessing an element of a slice is very fast. Go can look at a specific memory location to find an element's value very fast.
## Which one is the backing array of "slice2"?
```go
arr := [...]int{1, 2, 3}
slice1 := arr[2:3]
slice2 := slice1[:1]
```
1. arr *CORRECT*
2. slice1
3. slice2
4. A hidden backing array
> **1:** Yes! When a slice is created by slicing an array, that array becomes the backing array of that slice.
>
> **4:** Nope. That only happens when a slice doesn't being created from an array.
>
## Which one is the backing array of "slice"?
```go
arr := [...]int{1, 2, 3}
slice := []int{1, 2, 3}
```
1. arr
2. slice1
3. slice2
4. A hidden backing array *CORRECT*
> **1:** Nope, the slice hasn't created by slicing an array.
>
> **4:** Yes! A slice literal always creates a new hidden array.
>
## Which answer is correct for the following slices?
```go
slice1 := []int{1, 2, 3}
slice2 := []int{1, 2, 3}
```
1. Their backing array is the same.
2. Their backing arrays are different. *CORRECT*
3. They don't have any backing arrays.
> **2:** That's right. A slice literal always creates a new backing array.
## Which answer is correct for the following slices?
```go
slice1 := []int{1, 2, 3}
slice2 := []int{1, 2, 3}
slice3 := slice1[:]
slice4 := slice2[:]
```
1. slice1 and slice2 have the same backing arrays.
2. slice1 and slice3 have the same backing arrays. *CORRECT*
3. slice1 and slice4 have the same backing arrays.
4. slice3 and slice4 have the same backing arrays.
> **2:** Yep! A slice that is being created by slicing shares the same backing with the sliced slice. Here, slice3 is being created from slice1. That is also true for slice2 and slice4.
## What does the backing array of the nums slice look like?
```go
nums := []int{9, 7, 5, 3, 1}
nums = nums[:1]
fmt.Println(nums) // prints: [9]
```
1. [9 7 5 3 1] *CORRECT*
2. [7 5 3 1]
3. [9]
4. []
## What does this code print?
```go
arr := [...]int{9, 7, 5, 3, 1}
nums := arr[2:]
nums2 := nums[1:]
arr[2]++
nums[1] -= arr[4] - 4
nums2[1] += 5
fmt.Println(nums)
```
1. [5 3 1]
2. [6 6 6] *CORRECT*
3. [9 7 5]
> **2:** Yes! Because the backing array of `nums` and `nums2` is the same: `arr`. See the explanation here: https://play.golang.org/p/xTy0W0S_8PN
================================================
FILE: 16-slices/questions/5-slice-header.md
================================================
# Slice Header Quiz
## What is a slice header?
1. The first element of a slice value
2. The first element of the backing array
3. A tiny data structure that describes all or some part of a backing array *CORRECT*
4. A data structure that contains the elements of a slice
> **3:** Yes! It's just a tiny data structure with three numeric fields.
>
> **4:** A slice doesn't contain any elements on its own.
## What are the fields of a slice value?
1. Pointer, length, and capacity *CORRECT*
2. Length and capacity
3. Only a pointer
## Which slice value does the following slice header describe?
SLICE HEADER:
+ Pointer : 100th
+ Length : 5
+ Capacity: 10
Assume that the backing array is this one:
```go
var array [10]string
```
1. array[5:]
2. array[:5] *CORRECT*
3. array[3:]
4. array[100:]
> **1**: This slice's capacity is 5, it can only see the elements beginning with the 6th element.
>
> **2**: That's right. `array[:5]` returns a slice with the first 5 elements of the `array` (len is 5), but there are 5 more elements in the backing array of that slice, so in total its capacity is 10.
>
> **3**: This slice's capacity is 7, it can only see the elements beginning with the 4th element.
>
> **4**: This is an error. The backing array doesn't have 100 elements.
>
## Which one is the slice header of the following slice?
```go
var tasks []string
```
1. Pointer: 0, Length: 0, Capacity: 0 *CORRECT*
2. Pointer: 10, Length: 5, Capacity: 10
3. Pointer: 0, Length: 1, Capacity: 1
> **1:** A nil slice doesn't have backing array, so all the fields are equal to zero.
## What is the total memory usage of this code?
```go
var array [1000]int64
array2 := array
slice := array2[:]
```
1. 1024 bytes
2. 2024 bytes
3. 3000 bytes
4. 16024 bytes *CORRECT*
> **4:** `array` is 1000 x int64 (8 bytes) = 8000 bytes. Assigning an array copies all its elements, so `array2` adds additional 8000 bytes. A slice doesn't store anything on its own. Here, it's being created from array2, so it doesn't allocate a backing array as well. A slice header's size is 24 bytes. So in total: This program allocates 16024 bytes.
## What value does this code pass to the sort.Ints function?
```go
nums := []int{9, 7, 5, 3, 1}
sort.Ints(nums)
```
1. [9 7 5 3 1] — All the values of the nums slice
2. A pointer to the backing array of the nums slice
3. A pointer, length and capacity as three different arguments
4. The slice header that is stored in the nums variable *CORRECT*
> **1:** No, a slice value doesn't contain any elements. So it cannot pass the elements.
>
> **2:** Sorry but not only that.
>
> **3:** Nope. Remember, they are packed in a tiny data structure called the ....?
>
> **4:** Yep! A slice value is a slice header (pointer, length and capacity). A slice variable stores the slice header.
>
================================================
FILE: 16-slices/questions/6-capacity.md
================================================
# Capacity and Append Mechanics Quiz
## What is the difference between the length and capacity of a slice?
1. They are the same
2. The length is always greater than the capacity
3. The capacity is always greater than the capacity
4. The length describes the length of a slice but a capacity describes the length of the backing array beginning from the first element of the slice *CORRECT*
> **2:** The length is never greater than the capacity.
>
> **3:** The length and capacity of a slice can be equal.
## What is the capacity of a nil slice?
1. It is equal to its length + 1
2. It is nil
3. 0 *CORRECT*
4. 1
> **2:** The capacity's type is int, it cannot be nil.
## What are the length and capacity of the slice value?
```go
[]string{"I", "have", "a", "great", "capacity"}
```
1. Length: 5 - Capacity: 5 *CORRECT*
2. Length: 0 - Capacity: 5
3. Length: 5 - Capacity: 10
4. Length: 10 - Capacity: 10
> **1:** That's right! A slice literal creates a new slice value with equal length and capacity.
## What are the length and capacity of the 'words' slice?
```go
words := []string{"lucy", "in", "the", "sky", "with", "diamonds"}
words = words[:0]
```
1. Length: 0 - Capacity: 0
2. Length: 6 - Capacity: 6
3. Length: 0 - Capacity: 6 *CORRECT*
4. Length: 5 - Capacity: 10
> **3:** Right! `words[:0]` slices for 0 elements, which in turn returns a slice with zero-length. Because the `words` slice points to the same backing array, its capacity is equal to 6.
## What are the length and capacity of the 'words' slice?
```go
words := []string{"lucy", "in", "the", "sky", "with", "diamonds"}
words = words[0:]
```
1. Length: 0 - Capacity: 0
2. Length: 6 - Capacity: 6 *CORRECT*
3. Length: 0 - Capacity: 6
4. Length: 5 - Capacity: 10
> **2:** Right! `words[0:]` slices for the rest of the elements, which in turn returns a slice with the same length as the original slice: 6. Beginning from the first array element, the `words` slice's backing array contains 6 elements; so its capacity is also 6.
## What are the length and capacity of the 'words' slice?
```go
words := []string{"lucy", "in", "the", "sky", "with", "diamonds"}
words = words[2:cap(words)-2]
```
1. Length: 4 - Capacity: 6
2. Length: 6 - Capacity: 4
3. Length: 2 - Capacity: 6
4. Length: 2 - Capacity: 4 *CORRECT*
> **4:** Right! `words[2:cap(words)-2]` is equal to `words = words[2:4]`, so it returns: `["the" "sky"]`. So, its length is 2. But there are 4 more elements (`["the" "sky" "with" "diamonds"]`) in the backing array, so the capacity is 4.
================================================
FILE: 16-slices/questions/7-mechanics-of-append.md
================================================
# The Mechanics of Append Quiz
## Which append call below allocates a new backing array for the following slice?
```go
words := []string{"lucy", "in", "the", "sky", "with", "diamonds"}
```
1. words = append(words[:3], "crystals")
2. words = append(words[:4], "crystals")
3. words = append(words[:5], "crystals")
4. words = append(words[:5], "crystals", "and", "diamonds") *CORRECT*
> **1:** No, it just overwrites the 4th element.
>
> **2:** No, it just overwrites the 5th element.
>
> **3:** No, it just overwrites the last element.
>
> **4:** Yes, it overwrites the last element, then it adds two element. However, there is not enough space to do that, so it allocates a new backing array.
## What does the program print?
```go
words := []string{"lucy", "in", "the", "sky", "with", "diamonds"}
words = append(words[:1], "is", "everywhere")
words = append(words, words[len(words)+1:cap(words)]...)
```
1. lucy in the sky with diamonds
2. lucy is everywhere in the sky with diamonds
3. lucy is everywhere with diamonds *CORRECT*
4. lucy is everywhere
> **3:** line #2 overwrites the 2nd and 3rd elements. line #3 appends ["with" "diamonds"] after the ["lucy" "is" "everwhere"].
## What are the length and capacity of the words slice?
```go
// The words slice has 1023 elements.
//
// Tip: The keyed slice works like the same as a keyed array.
// If you don't remember how it works, please check out the keyed elements in the arrays section.
//
words := []string{1022: ""}
words = append(words, "boom!")
```
1. Length: 1024 - Capacity: 1024
2. Length: 1025 - Capacity: 1025
3. Length: 1025 - Capacity: 1280
4. Length: 1024 - Capacity: 2048 *CORRECT*
> **4:** That's right! Append function grows by doubling the capacity of the previous slice.
## What are the length and capacity of the words slice?
```go
// The words slice has 1024 elements.
//
// Tip: The keyed slice works like the same as a keyed array.
// If you don't remember how it works, please check out the keyed elements in the arrays section.
//
words := []string{1023: ""}
words = append(words, "boom!")
```
1. Length: 1024 - Capacity: 1024
2. Length: 1025 - Capacity: 1025
3. Length: 1025 - Capacity: 1280 *CORRECT*
4. Length: 1025 - Capacity: 2048
> **3, 4:** After 1024 elements, the append function grows at a slower rate, about 25%.
================================================
FILE: 16-slices/questions/8-advanced-ops.md
================================================
# Advanced Slice Operations Quiz
## What are the length and capacity of the 'part' slice?
```go
lyric := []string{"show", "me", "my", "silver", "lining"}
part := lyric[1:3:5]
```
1. Length: 1 - Capacity: 5
2. Length: 1 - Capacity: 3
3. Length: 3 - Capacity: 5
4. Length: 2 - Capacity: 4 *CORRECT*
> **4:** General Formula: `[low:high:max]` => `length = high - max` and `capacity = max - low`. `lyric[1:3]` is `["me" "my"]`. `lyric[1:3:5]` is `["me" "my" "silver" "lining"]`. So, `[1:3]` is the returned slice, length: 2. `[1:3:5]` limits the capacity to four because after the 1st element there are only four more elements.
## What are the lengths and capacities of the slices below?
```go
lyric := []string{"show", "me", "my", "silver", "lining"}
part := lyric[:2:2]
part = append(part, "right", "place")
```
1. lyric's len: 5, cap: 5 — part's len: 5, cap: 5
2. lyric's len: 3, cap: 1 — part's len: 2, cap: 3
3. lyric's len: 5, cap: 5 — part's len: 4, cap: 4 *CORRECT*
4. lyric's len: 3, cap: 1 — part's len: 2, cap: 3
> **3:** `lyric[:2:2]` = ["show" "me"]. After the append the part becomes: ["show" "me" "right" "place"] — so it allocates a new backing array. `lyric` stays the same: `["show" "me" "my" "silver" "lining"]`.
## When you might want to use the make function?
1. To preallocate a backing array for a slice with a definite length *CORRECT*
2. To create a slice faster
3. To use less memory
> **1:** Yes! You can use the make function to preallocate a backing array for a slice upfront.
## What does the program print?
```go
tasks := make([]string, 2)
tasks = append(tasks, "hello", "world")
fmt.Printf("%q\n", tasks)
```
1. ["" "" "hello" "world"] *CORRECT*
2. ["hello" "world"]
3. ["hello" "world" "" ""]
> **1:** `make([]string, 2)` creates a slice with len: 2 and cap: 2, and it sets all the elements to their zero-values. `append()` appends after the length of the slice (after the first two elements). That's why the first two elements are zero-valued strings but the last two elements are the newly appended elements.
## What does the program print?
```go
tasks := make([]string, 0, 2)
tasks = append(tasks, "hello", "world")
fmt.Printf("%q\n", tasks)
```
1. ["" "" "hello" "world"]
2. ["hello" "world"] *CORRECT*
3. ["hello" "world" "" ""]
> **2:** `make([]string, 0, 2)` creates a slice with len: 0 and cap: 2. `append()` appends after the length of the slice (at the beginning). That's why the first two elements are overwritten with the newly appended elements. This is a common usage pattern when you want to use the `make` and the `append` functions together.
## What does the program print?
```go
lyric := []string{"le", "vent", "nous", "portera"}
n := copy(lyric, make([]string, 4))
fmt.Printf("%d %q\n", n, lyric)
// -- USEFUL INFORMATION (but not required to solve the question) --
// In the following `copy` operation, `make` won't allocate
// a slice with a new backing array up to 32768 bytes
// (one string value is 8 bytes on a 64-bit machine).
//
// This is an optimization made by the Go compiler.
```
1. 4 ["le" "vent" "le" "vent"]
2. 4 ["le" "vent" "nous" "portera"]
3. 4 ["" "" "" ""] *CORRECT*
4. 0 []
> **3:** `copy` copies a newly created slice with four elements (`make([]string, 4)`) onto `lyric` slice. They both have 4 elements, so the `copy` copies 4 elements. Remember: `make()` initializes a slice with zero-values of its element type. Here, this operation clears all the slice elements to their zero-values.
## What does the program print?
```go
spendings := [][]int{{200, 100}, {}, {50, 25, 75}, {500}}
total := spendings[2][1] + spendings[3][0] + spendings[0][0]
fmt.Printf("%d\n", total)
```
1. 725 *CORRECT*
2. 650
3. 500
4. 750
> **1:** `spendings[2][1]` = 25. `spendings[3][0]` = 500. `spendings[0][0]` = 200. 25 + 500 + 200 = 725
## What does the program print?
```go
spendings := [][]int{{1,2}}
// REMEMBER: %T prints the type of a given value
fmt.Printf("%T - ", spendings)
fmt.Printf("%T - ", spendings[0])
fmt.Printf("%T", spendings[0][0])
```
1. [][]int{{1, 2}} - []int{1, 2} - int(2)
2. [][]int - []int - int *CORRECT*
3. []int - int - 2
4. [][]int - [][]int - []int
> **2:** `spendings` is a 2-dimensional int slice, so its type is [][]int. Its element type is: `[]int`, so: `spendings[0]` is `[]int`. `spendings[0]`'s element type is: `int`. So `spendings[0][0]`'s type is `int`.
## What is the 'element type' of the slice?
```go
[][][3]int{{{10, 5, 9}}}
```
1. [][][3]int
2. [][]int
3. [][3]int *CORRECT*
4. [3]int
> **3:** `[][][3]int` is a multi-dimensional slice of `[][3]int` elements. `[][3]int` is a multi-dimensional slice of `[3]int` elements. `[3]int` is an array of 3 `int` values.
================================================
FILE: 16-slices/questions/README.md
================================================
# Slice Quizzes
* [Slices vs Arrays](1-slices-vs-arrays.md)
* [Appending](2-appending.md)
* [Slicing](3-slicing.md)
* [Backing Array](4-backing-array.md)
* [Slice Header](5-slice-header.md)
* [Capacity](6-capacity.md)
* [The Mechanics of Append](7-mechanics-of-append.md)
* [Advanced Slice Operations](8-advanced-ops.md)
================================================
FILE: 17-project-empty-file-finder/01-fetch-the-files/files/empty1.txt
================================================
================================================
FILE: 17-project-empty-file-finder/01-fetch-the-files/files/empty2.txt
================================================
================================================
FILE: 17-project-empty-file-finder/01-fetch-the-files/files/empty3.txt
================================================
================================================
FILE: 17-project-empty-file-finder/01-fetch-the-files/files/nonEmpty1.txt
================================================
learngoprogramming.com
================================================
FILE: 17-project-empty-file-finder/01-fetch-the-files/files/nonEmpty2.txt
================================================
learngoprogramming.com
================================================
FILE: 17-project-empty-file-finder/01-fetch-the-files/files/nonEmpty3.txt
================================================
learngoprogramming.com
================================================
FILE: 17-project-empty-file-finder/01-fetch-the-files/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
args := os.Args[1:]
if len(args) == 0 {
fmt.Println("Provide a directory")
return
}
files, err := ioutil.ReadDir(args[0])
if err != nil {
fmt.Println(err)
return
}
for _, file := range files {
if file.Size() == 0 {
name := file.Name()
fmt.Println(name)
}
}
}
================================================
FILE: 17-project-empty-file-finder/02-write-to-a-file/files/empty1.txt
================================================
================================================
FILE: 17-project-empty-file-finder/02-write-to-a-file/files/empty2.txt
================================================
================================================
FILE: 17-project-empty-file-finder/02-write-to-a-file/files/empty3.txt
================================================
================================================
FILE: 17-project-empty-file-finder/02-write-to-a-file/files/nonEmpty1.txt
================================================
learngoprogramming.com
================================================
FILE: 17-project-empty-file-finder/02-write-to-a-file/files/nonEmpty2.txt
================================================
learngoprogramming.com
================================================
FILE: 17-project-empty-file-finder/02-write-to-a-file/files/nonEmpty3.txt
================================================
learngoprogramming.com
================================================
FILE: 17-project-empty-file-finder/02-write-to-a-file/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
args := os.Args[1:]
if len(args) == 0 {
fmt.Println("Provide a directory")
return
}
files, err := ioutil.ReadDir(args[0])
if err != nil {
fmt.Println(err)
return
}
var names []byte
for _, file := range files {
if file.Size() == 0 {
name := file.Name()
fmt.Println(cap(names))
names = append(names, name...)
names = append(names, '\n')
}
}
err = ioutil.WriteFile("out.txt", names, 0644)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%s", names)
}
// See: https://www.tutorialspoint.com/unix/unix-file-permission.htm
// See: http://permissions-calculator.org/
================================================
FILE: 17-project-empty-file-finder/03-optimize/files/empty1.txt
================================================
================================================
FILE: 17-project-empty-file-finder/03-optimize/files/empty2.txt
================================================
================================================
FILE: 17-project-empty-file-finder/03-optimize/files/empty3.txt
================================================
================================================
FILE: 17-project-empty-file-finder/03-optimize/files/nonEmpty1.txt
================================================
learngoprogramming.com
================================================
FILE: 17-project-empty-file-finder/03-optimize/files/nonEmpty2.txt
================================================
learngoprogramming.com
================================================
FILE: 17-project-empty-file-finder/03-optimize/files/nonEmpty3.txt
================================================
learngoprogramming.com
================================================
FILE: 17-project-empty-file-finder/03-optimize/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
args := os.Args[1:]
if len(args) == 0 {
fmt.Println("Provide a directory")
return
}
files, err := ioutil.ReadDir(args[0])
if err != nil {
fmt.Println(err)
return
}
// 1st: You can also take the average of the total file length
// across platforms. It's about 255.
//
// https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits
//
// BTRFS 255 bytes
// exFAT 255 UTF-16 characters
// ext2 255 bytes
// ext3 255 bytes
// ext3cow 255 bytes
// ext4 255 bytes
// FAT32 255 bytes
// NTFS 255 characters
// XFS 255 bytes
//
// total := len(files) * 256
// 1st B: To be exact, find the total size of all the empty files
var total int
for _, file := range files {
if file.Size() == 0 {
// +1 for the newline character
// when printing the filename afterward
total += len(file.Name()) + 1
}
}
fmt.Printf("Total required space: %d bytes.\n", total)
// 2nd: allocate a large enough byte slice in one go
names := make([]byte, 0, total)
for _, file := range files {
if file.Size() == 0 {
name := file.Name()
names = append(names, name...)
names = append(names, '\n')
}
}
err = ioutil.WriteFile("out.txt", names, 0644)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%s", names)
}
// See: https://www.tutorialspoint.com/unix/unix-file-permission.htm
// See: http://permissions-calculator.org/
================================================
FILE: 17-project-empty-file-finder/exercises/1-sort-to-a-file/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Sort and write items to a file
//
// 1. Get arguments from command-line
//
// 2. Sort them
//
// 3. Write the sorted slice to a file
//
//
// EXPECTED OUTPUT
//
// go run main.go
// Send me some items and I will sort them
//
// go run main.go orange banana apple
//
// cat sorted.txt
// apple
// banana
// orange
//
//
// HINTS
//
// + REMEMBER: os.Args is a []string
//
// + String slices are sortable using `sort.Strings`
//
// + Use ioutil.WriteFile to write to a file.
//
// + But you need to convert []string to []byte to be able to
// write it to a file using the ioutil.WriteFile.
//
// + To do that, create a new []byte and append the elements of your
// []string.
//
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 17-project-empty-file-finder/exercises/1-sort-to-a-file/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io/ioutil"
"os"
"sort"
)
func main() {
items := os.Args[1:]
if len(items) == 0 {
fmt.Println("Send me some items and I will sort them")
return
}
sort.Strings(items)
var data []byte
for _, s := range items {
data = append(data, s...)
data = append(data, '\n')
}
err := ioutil.WriteFile("sorted.txt", data, 0644)
if err != nil {
fmt.Println(err)
return
}
}
================================================
FILE: 17-project-empty-file-finder/exercises/2-sort-to-a-file-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io/ioutil"
"os"
"sort"
)
// ---------------------------------------------------------
// EXERCISE: Sort and write items to a file with their ordinals
//
// Use the previous exercise.
//
// This time, print the sorted items with ordinals
// (see the expected output)
//
//
// EXPECTED OUTPUT
//
// go run main.go
// Send me some items and I will sort them
//
// go run main.go orange banana apple
//
// cat sorted.txt
// 1. apple
// 2. banana
// 3. orange
//
//
// HINTS
//
// ONLY READ THIS IF YOU GET STUCK
//
// + You can use strconv.AppendInt function to append an int
// to a byte slice. strconv contains a lot of functions for appending
// other basic types to []byte slices as well.
//
// + You can append individual characters to a byte slice using
// rune literals (because: rune literal are typeless numerics):
//
// var slice []byte
// slice = append(slice, 'h', 'i', ' ', '!')
// fmt.Printf("%s\n", slice)
//
// Above code prints: hi !
// ---------------------------------------------------------
func main() {
items := os.Args[1:]
if len(items) == 0 {
fmt.Println("Send me some items and I will sort them")
return
}
sort.Strings(items)
var data []byte
for _, s := range items {
data = append(data, s...)
data = append(data, '\n')
}
err := ioutil.WriteFile("sorted.txt", data, 0644)
if err != nil {
fmt.Println(err)
return
}
}
================================================
FILE: 17-project-empty-file-finder/exercises/2-sort-to-a-file-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io/ioutil"
"os"
"sort"
"strconv"
)
func main() {
items := os.Args[1:]
if len(items) == 0 {
fmt.Println("Send me some items and I will sort them")
return
}
sort.Strings(items)
var data []byte
for i, s := range items {
data = strconv.AppendInt(data, int64(i+1), 10)
data = append(data, '.', ' ')
data = append(data, s...)
data = append(data, '\n')
}
err := ioutil.WriteFile("sorted.txt", data, 0644)
if err != nil {
fmt.Println(err)
return
}
}
================================================
FILE: 17-project-empty-file-finder/exercises/3-print-directories/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Find and write the names of subdirectories to a file
//
// Create a program that can get multiple directory paths from
// the command-line, and prints only their subdirectories into a
// file named: dirs.txt
//
//
// 1. Get the directory paths from command-line
//
// 2. Append the names of subdirectories inside each directory
// to a byte slice
//
// 3. Write that byte slice to dirs.txt file
//
//
// EXPECTED OUTPUT
//
// go run main.go
// Please provide directory paths
//
// go run main.go dir/ dir2/
//
// cat dirs.txt
//
// dir/
// subdir1/
// subdir2/
//
// dir2/
// subdir1/
// subdir2/
// subdir3/
//
//
// HINTS
//
// ONLY READ THIS IF YOU GET STUCK
//
// + Get all the files in a directory using ioutil.ReadDir
// (A directory is also a file)
//
// + You can use IsDir method of a FileInfo value to detect
// whether a file is a directory or not.
//
// Check out its documentation:
//
// go doc os.FileInfo.IsDir
//
// # or using godocc
// godocc os.FileInfo.IsDir
//
// + You can use '\t' escape sequence for indenting the subdirs.
//
// + You can find a sample directory structure under:
// solution/ directory
//
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 17-project-empty-file-finder/exercises/3-print-directories/solution/dir/.gitignore
================================================
*
!subdir1
!subdir2
!.gitignore
================================================
FILE: 17-project-empty-file-finder/exercises/3-print-directories/solution/dir/subdir1/.gitignore
================================================
*
!.gitignore
================================================
FILE: 17-project-empty-file-finder/exercises/3-print-directories/solution/dir/subdir2/.gitignore
================================================
*
!.gitignore
================================================
FILE: 17-project-empty-file-finder/exercises/3-print-directories/solution/dir2/.gitignore
================================================
*
!subdir1
!subdir2
!subdir3
!.gitignore
================================================
FILE: 17-project-empty-file-finder/exercises/3-print-directories/solution/dir2/subdir1/.gitignore
================================================
*
!.gitignore
================================================
FILE: 17-project-empty-file-finder/exercises/3-print-directories/solution/dir2/subdir2/.gitignore
================================================
*
!.gitignore
================================================
FILE: 17-project-empty-file-finder/exercises/3-print-directories/solution/dir2/subdir3/.gitignore
================================================
*
!.gitignore
================================================
FILE: 17-project-empty-file-finder/exercises/3-print-directories/solution/dirs.txt
================================================
dir/
subdir1/
subdir2/
dir2/
subdir1/
subdir2/
subdir3/
================================================
FILE: 17-project-empty-file-finder/exercises/3-print-directories/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
paths := os.Args[1:]
if len(paths) == 0 {
fmt.Println("Please provide directory paths")
return
}
var dirs []byte
for _, dir := range paths {
files, err := ioutil.ReadDir(dir)
if err != nil {
fmt.Println(err)
return
}
dirs = append(dirs, dir...)
dirs = append(dirs, '\n')
for _, file := range files {
if file.IsDir() {
dirs = append(dirs, '\t')
dirs = append(dirs, file.Name()...)
dirs = append(dirs, '/', '\n')
}
}
dirs = append(dirs, '\n')
}
err := ioutil.WriteFile("dirs.txt", dirs, 0644)
if err != nil {
fmt.Println(err)
return
}
}
================================================
FILE: 17-project-empty-file-finder/exercises/README.md
================================================
# Empty File Finder Exercises
1. **[Sort and write items to a file](https://github.com/inancgumus/learngo/tree/master/17-project-empty-file-finder/exercises/1-sort-to-a-file)**
2. **[Sort and write items to a file with their ordinals](https://github.com/inancgumus/learngo/tree/master/17-project-empty-file-finder/exercises/2-sort-to-a-file-2)**
3. **[Find and write the names of subdirectories to a file](https://github.com/inancgumus/learngo/tree/master/17-project-empty-file-finder/exercises/3-print-directories)**
================================================
FILE: 18-project-bouncing-ball/01-draw-the-board/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
const (
width = 50
height = 10
cellEmpty = ' '
cellBall = '⚾'
)
var cell rune // current cell (for caching)
// create the board
board := make([][]bool, width)
for column := range board {
board[column] = make([]bool, height)
}
// draw a smiley
board[12][2] = true
board[16][2] = true
board[14][4] = true
board[10][6] = true
board[18][6] = true
board[12][7] = true
board[14][7] = true
board[16][7] = true
// print the board directly to the console
for y := range board[0] {
for x := range board {
cell = cellEmpty
if board[x][y] {
cell = cellBall
}
fmt.Print(string(cell), " ")
}
fmt.Println()
}
}
================================================
FILE: 18-project-bouncing-ball/02-add-a-buffer/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
const (
width = 50
height = 10
cellEmpty = ' '
cellBall = '⚾'
)
var cell rune // current cell (for caching)
// create the board
board := make([][]bool, width)
for column := range board {
board[column] = make([]bool, height)
}
// create a drawing buffer
buf := make([]rune, 0, width*height)
// draw a smiley
board[12][2] = true
board[16][2] = true
board[14][4] = true
board[10][6] = true
board[18][6] = true
board[12][7] = true
board[14][7] = true
board[16][7] = true
// use the loop for measuring the performance difference
for i := 0; i < 1000; i++ {
// rewind the buffer so that the program reuses it
buf = buf[:0]
// draw the board into the buffer
for y := range board[0] {
for x := range board {
cell = cellEmpty
if board[x][y] {
cell = cellBall
}
// fmt.Print(string(cell), " ")
buf = append(buf, cell, ' ')
}
// fmt.Println()
buf = append(buf, '\n')
}
// print the buffer
fmt.Print(string(buf))
}
}
================================================
FILE: 18-project-bouncing-ball/03-animate/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
const (
width = 50
height = 10
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
)
var (
px, py int // ball position
vx, vy = 1, 1 // velocities
cell rune // current cell (for caching)
)
// create the board
board := make([][]bool, width)
for column := range board {
board[column] = make([]bool, height)
}
// create a drawing buffer
buf := make([]rune, 0, width*height)
// clear the screen once
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-1 {
vx *= -1
}
if py <= 0 || py >= height-1 {
vy *= -1
}
// remove the previous ball
for y := range board[0] {
for x := range board {
board[x][y] = false
}
}
// put the new ball
board[px][py] = true
// rewind the buffer (allow appending from the beginning)
buf = buf[:0]
// draw the board into the buffer
for y := range board[0] {
for x := range board {
cell = cellEmpty
if board[x][y] {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
// print the buffer
screen.MoveTopLeft()
fmt.Print(string(buf))
// slow down the animation
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/README.md
================================================
# Bouncing Ball Challenge Tips
Use the following tips only when you get stuck. This document isn't in a particular order, please do not follow it like so.
## CALCULATING THE VELOCITY
You can use velocity to change the ball's speed and position. In my example, the speed is constant, so I always use unit value: 1.
* On each loop step: Add velocities to ball's position. This will make the ball move.
* **Velocity means: Speed and Direction**
* X velocity = 1 -> _ball moves right_
* X velocity = -1 -> _ball moves left_
* Y velocity = 1 -> _ball moves down_
* Y velocity = -1 -> _ball moves up_
* **For more information on graphics and velocity:**
* [Youtube: Crash Course: 2D Graphics](https://www.youtube.com/watch?v=7Jr0SFMQ4Rs&t=529)
* [Youtube: Crash Course: Velocity](https://www.youtube.com/watch?v=ZM8ECpBuQYE)
## CREATING THE BOARD
I use `[][]bool` for the board but you can use anything you like. For example, you can directly use `[][]rune` or `[]rune`. Experiment with them and decide which one is the best for you.
## CLEARING THE SCREEN
* Before the loop, clear the screen once by using my [screen package](https://github.com/inancgumus/screen), click on the link. You can find its [documentation here](https://godoc.org/github.com/inancgumus/screen).
* After each loop step, move the cursor to the top-left position by using the screen package. So that you can draw the animation frame all over again in the same position.
* You can find more information about the screen package and screen clearing in the [Retro Clock project section lectures](https://github.com/inancgumus/learngo/tree/master/15-project-retro-led-clock).
## DRAWING THE BOARD
Instead of drawing the board and the ball to the screen everytime, you will fill a buffer, and when you complete, you can draw the board and the ball once by printing the buffer. I use a `[]rune` slice as a buffer because `rune` can store an emoji character.
* Make a large enough rune slice named `buf` using the `make` function.
* **HINT:** `width * height` will give you a large enough buffer.
* **TIP:** You could also use `string` concatenation to draw into a `string` buffer but it would be inefficient.
* You will find more information about bytes and runes in the strings section.
```go
// TIP for converting the buffer
var buffer []rune
// For printing, you can convert a rune slice to a string like so:
str := string(buffer)
```
## SLOWING DOWN THE SPEED
Call the `time.Sleep` function to slow down the speed of the loop a little bit, so you can see the ball :)
```go
time.Sleep(time.Second / 20)
```
================================================
FILE: 18-project-bouncing-ball/exercises/01-find-the-bug/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
// ---------------------------------------------------------
// EXERCISE: Find the Bug
//
// As I've annotated in the lectures, there is a bug
// in this code. Please find the bug and fix it.
//
//
// HINT #1
//
// 💀 Read this only if you get stuck.
//
// Print the width*height and the capacity of the drawing buffer
// after a single drawing loop ends. You might be surprised.
//
//
// HINT #2
//
// 💀 Read this only if you get stuck.
//
// The bug is in the drawing buffer. It doesn't include the
// newline and space characters when creating the buffer. So
// the buffer is not large enough to hold all the characters.
// So new backing arrays are getting allocated.
//
// ---------------------------------------------------------
func main() {
const (
width = 50
height = 10
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
)
var (
px, py int // ball position
vx, vy = 1, 1 // velocities
cell rune // current cell (for caching)
)
// create the board
board := make([][]bool, width)
for column := range board {
board[column] = make([]bool, height)
}
// create a drawing buffer
buf := make([]rune, 0, width*height)
// clear the screen once
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-1 {
vx *= -1
}
if py <= 0 || py >= height-1 {
vy *= -1
}
// remove the previous ball
for y := range board[0] {
for x := range board {
board[x][y] = false
}
}
// put the new ball
board[px][py] = true
// rewind the buffer (allow appending from the beginning)
buf = buf[:0]
// draw the board into the buffer
for y := range board[0] {
for x := range board {
cell = cellEmpty
if board[x][y] {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
// print the buffer
screen.MoveTopLeft()
fmt.Print(string(buf))
// slow down the animation
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/exercises/01-find-the-bug/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
func main() {
const (
width = 50
height = 10
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
// drawing buffer length
// *2 for extra spaces
// +1 for newlines
bufLen = (width*2 + 1) * height
)
var (
px, py int // ball position
vx, vy = 1, 1 // velocities
cell rune // current cell (for caching)
)
// create the board
board := make([][]bool, width)
for column := range board {
board[column] = make([]bool, height)
}
// create a drawing buffer
// BUG FIXED!
buf := make([]rune, 0, bufLen)
// clear the screen once
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-1 {
vx *= -1
}
if py <= 0 || py >= height-1 {
vy *= -1
}
// remove the previous ball
for y := range board[0] {
for x := range board {
board[x][y] = false
}
}
// put the new ball
board[px][py] = true
// rewind the buffer (allow appending from the beginning)
buf = buf[:0]
// draw the board into the buffer
for y := range board[0] {
for x := range board {
cell = cellEmpty
if board[x][y] {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
// print the buffer
screen.MoveTopLeft()
fmt.Print(string(buf))
// slow down the animation
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/exercises/02-width-and-height/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
)
// ---------------------------------------------------------
// EXERCISE: Adjust the width and height automatically
//
// Instead of setting the width and height manually,
// you need to get the width and height of the terminal
// screen from your operating system.
//
// 1. Update your program to use my screen package.
// It offers an easy way to get the width and height.
//
// go get -u https://github.com/inancgumus/screen
//
// 2. Read the package's documentation and find a way to
// get the screen size: width and height.
//
// The documentation is here:
// https://godoc.org/github.com/inancgumus/screen
//
// 3. Use it to set the board's dimensions.
//
//
// OPTIONAL EXERCISE
//
// 1. When you set the width, you may see that the ball
// goes beyond the left and right borders. This happens
// because the ball emoji spans to multiple console
// columns (or cells). Ordinary characters have a
// single column.
//
// 1. Get the width of the ball emoji using a function
// from the following package:
//
// go get -u github.com/mattn/go-runewidth
//
// 2. Divide the width using the rune width of the
// ball emoji.
//
// 2. Your terminal may have borders, so reduce the
// height by taking into account the height of
// your terminal borders.
//
//
// EXPECTED OUTPUT
//
// When you run the program, the ball should start
// animating across the total width and height of your
// terminal screen dynamically.
//
// Currently you set width and height manually, so it
// wasn't matter whether your terminal was bigger or
// smaller, but now it will be!
//
// ---------------------------------------------------------
func main() {
const (
width = 50
height = 10
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
// drawing buffer length
//
// *2 for extra spaces
// +1 for newlines
bufLen = (width*2 + 1) * height
)
var (
px, py int // ball position
vx, vy = 1, 1 // velocities
cell rune // current cell (for caching)
)
// create the board
board := make([][]bool, width)
for column := range board {
board[column] = make([]bool, height)
}
// create a drawing buffer
buf := make([]rune, 0, bufLen)
// clear the screen once
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-1 {
vx *= -1
}
if py <= 0 || py >= height-1 {
vy *= -1
}
// remove the previous ball
for y := range board[0] {
for x := range board {
board[x][y] = false
}
}
// put the new ball
board[px][py] = true
// rewind the buffer (allow appending from the beginning)
buf = buf[:0]
// draw the board into the buffer
for y := range board[0] {
for x := range board {
cell = cellEmpty
if board[x][y] {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
// print the buffer
screen.MoveTopLeft()
fmt.Print(string(buf))
// slow down the animation
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/exercises/02-width-and-height/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/mattn/go-runewidth"
"github.com/inancgumus/screen"
)
func main() {
const (
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
)
var (
px, py int // ball position
vx, vy = 1, 1 // velocities
cell rune // current cell (for caching)
)
// you can get the width and height using the screen package easily:
width, height := screen.Size()
// get the rune width of the ball emoji
ballWidth := runewidth.RuneWidth(cellBall)
// adjust the width and height
width /= ballWidth
height-- // there is a 1 pixel border in my terminal
// create the board
board := make([][]bool, width)
for column := range board {
board[column] = make([]bool, height)
}
// drawing buffer length
// *2 for extra spaces
// +1 for newlines
bufLen := (width*2 + 1) * height
// create a drawing buffer
buf := make([]rune, 0, bufLen)
// clear the screen once
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-1 {
vx *= -1
}
if py <= 0 || py >= height-1 {
vy *= -1
}
// remove the previous ball
for y := range board[0] {
for x := range board {
board[x][y] = false
}
}
// put the new ball
board[px][py] = true
// rewind the buffer (allow appending from the beginning)
buf = buf[:0]
// draw the board into the buffer
for y := range board[0] {
for x := range board {
cell = cellEmpty
if board[x][y] {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
// print the buffer
screen.MoveTopLeft()
fmt.Print(string(buf))
// slow down the animation
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/exercises/03-previous-positions/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
"github.com/mattn/go-runewidth"
)
// ---------------------------------------------------------
// EXERCISE: Previous positions
//
// Let's optimize the program once more. This time you're
// going to optimize the clearing off the previous positions.
//
// 1. Find the code below marked as "remove the previous ball"
//
// 2. Instead of clearing every position on the board to false,
// only set the previous position to false. So, don't use
// a loop, remove it.
//
// 3. Change the velocity of the ball like so:
//
// vx, vy = 5, 2
//
// 4. Run the program and solve the problem
//
//
// HINT
//
// Don't forget saving the previous position.
//
// ---------------------------------------------------------
func main() {
const (
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
)
var (
px, py int // ball position
vx, vy = 1, 1 // velocities
cell rune // current cell (for caching)
)
// you can get the width and height using the screen package easily:
width, height := screen.Size()
// get the rune width of the ball emoji
ballWidth := runewidth.RuneWidth(cellBall)
// adjust the width and height
width /= ballWidth
height-- // there is a 1 pixel border in my terminal
// create the board
board := make([][]bool, width)
for column := range board {
board[column] = make([]bool, height)
}
// drawing buffer length
// *2 for extra spaces
// +1 for newlines
bufLen := (width*2 + 1) * height
// create a drawing buffer
buf := make([]rune, 0, bufLen)
// clear the screen once
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-1 {
vx *= -1
}
if py <= 0 || py >= height-1 {
vy *= -1
}
// remove the previous ball
for y := range board[0] {
for x := range board {
board[x][y] = false
}
}
// put the new ball
board[px][py] = true
// rewind the buffer (allow appending from the beginning)
buf = buf[:0]
// draw the board into the buffer
for y := range board[0] {
for x := range board {
cell = cellEmpty
if board[x][y] {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
// print the buffer
screen.MoveTopLeft()
fmt.Print(string(buf))
// slow down the animation
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/exercises/03-previous-positions/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
"github.com/mattn/go-runewidth"
)
func main() {
const (
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
// initial velocities
ivx, ivy = 5, 2
)
var (
px, py int // ball position
ppx, ppy int // previous ball position
vx, vy = ivx, ivx // velocities
cell rune // current cell (for caching)
)
// you can get the width and height using the screen package easily:
width, height := screen.Size()
// get the rune width of the ball emoji
ballWidth := runewidth.RuneWidth(cellBall)
// adjust the width and height
width /= ballWidth
height-- // there is a 1 pixel border in my terminal
// create the board
board := make([][]bool, width)
for column := range board {
board[column] = make([]bool, height)
}
// drawing buffer length
// *2 for extra spaces
// +1 for newlines
bufLen := (width*2 + 1) * height
// create a drawing buffer
buf := make([]rune, 0, bufLen)
// clear the screen once
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-ivx {
vx *= -1
}
if py <= 0 || py >= height-ivx {
vy *= -1
}
// remove the previous ball and put the new ball
board[px][py], board[ppx][ppy] = true, false
// save the previous positions
ppx, ppy = px, py
// rewind the buffer (allow appending from the beginning)
buf = buf[:0]
// draw the board into the buffer
for y := range board[0] {
for x := range board {
cell = cellEmpty
if board[x][y] {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
// print the buffer
screen.MoveTopLeft()
fmt.Print(string(buf))
// slow down the animation
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/exercises/04-single-dimensional/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
"github.com/mattn/go-runewidth"
)
// ---------------------------------------------------------
// EXERCISE: Single Dimensional
//
// In this exercise you will understand why I use
// a multi-dimensional board slice instead of a
// single-dimensional one.
//
// 1. Remove this:
// board := make([][]bool, width)
//
// 2. Use this:
// board := make([]bool, width*height)
//
// 3. Adjust the rest of the operations in the code to work
// with this single-dimensional slice.
//
// You'll see how hard it becomes to work with it.
//
// ---------------------------------------------------------
func main() {
const (
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
// initial velocities
ivx, ivy = 5, 2
)
var (
px, py int // ball position
ppx, ppy int // previous ball position
vx, vy = ivx, ivy // velocities
cell rune // current cell (for caching)
)
// you can get the width and height using the screen package easily:
width, height := screen.Size()
// get the rune width of the ball emoji
ballWidth := runewidth.RuneWidth(cellBall)
// adjust the width and height
width /= ballWidth
height-- // there is a 1 pixel border in my terminal
// create the board
board := make([][]bool, width)
for column := range board {
board[column] = make([]bool, height)
}
// drawing buffer length
// *2 for extra spaces
// +1 for newlines
bufLen := (width*2 + 1) * height
// create a drawing buffer
buf := make([]rune, 0, bufLen)
// clear the screen once
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-ivx {
vx *= -1
}
if py <= 0 || py >= height-ivy {
vy *= -1
}
// remove the previous ball and put the new ball
board[px][py], board[ppx][ppy] = true, false
// save the previous positions
ppx, ppy = px, py
// rewind the buffer (allow appending from the beginning)
buf = buf[:0]
// draw the board into the buffer
for y := range board[0] {
for x := range board {
cell = cellEmpty
if board[x][y] {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
// print the buffer
screen.MoveTopLeft()
fmt.Print(string(buf))
// slow down the animation
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/exercises/04-single-dimensional/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
"github.com/mattn/go-runewidth"
)
func main() {
const (
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
// initial velocities
ivx, ivy = 5, 2
)
var (
px, py int // ball position
ppx, ppy int // previous ball position
vx, vy = ivx, ivy // velocities
cell rune // current cell (for caching)
)
// you can get the width and height using the screen package easily:
width, height := screen.Size()
// get the rune width of the ball emoji
ballWidth := runewidth.RuneWidth(cellBall)
// adjust the width and height
width /= ballWidth
height-- // there is a 1 pixel border in my terminal
// create a single-dimensional board
board := make([]bool, width*height)
// drawing buffer length
// *2 for extra spaces
// +1 for newlines
bufLen := (width*2 + 1) * height
// create a drawing buffer
buf := make([]rune, 0, bufLen)
// clear the screen once
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-ivx {
vx *= -1
}
if py <= 0 || py >= height-ivy {
vy *= -1
}
// calculate the new and the previous ball positions
pos := py*width + px
ppos := ppy*width + ppx
// remove the previous ball and put the new ball
board[pos], board[ppos] = true, false
// save the previous positions
ppx, ppy = px, py
// rewind the buffer (allow appending from the beginning)
buf = buf[:0]
// draw the board into the buffer
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
cell = cellEmpty
if board[y*width+x] {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
// print the buffer
screen.MoveTopLeft()
fmt.Print(string(buf))
// slow down the animation
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/exercises/05-no-slice/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
"github.com/mattn/go-runewidth"
)
// ---------------------------------------------------------
// EXERCISE: No Slice
//
// Can you modify the program so that it doesn't use a
// slice for the board. You can use a slice for the buffer
// though.
//
// In this exercise, you'll understand that you don't
// have to use slices in any problem you encounter with.
//
// See what it feels like not using a slice for this
// solution.
//
// Think about why you have to use a slice for the buffer?
//
// Can there be any other solution?
//
// ---------------------------------------------------------
func main() {
const (
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
ivx, ivy = 1, 1 // initial velocities
)
var (
px, py int // ball position
ppx, ppy int // previous ball position
vx, vy = ivx, ivy // velocities
cell rune // current cell (for caching)
)
width, height := screen.Size()
width /= runewidth.RuneWidth(cellBall)
height-- // there is a 1 pixel border in my terminal
// REMOVE THIS: create a single-dimensional board
board := make([]bool, width*height)
// create a drawing buffer
// *2 for extra spaces
// +1 for newlines
buf := make([]rune, 0, (width*2+1)*height)
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-ivx {
vx *= -1
}
if py <= 0 || py >= height-ivy {
vy *= -1
}
// remove the previous ball and put the new ball
pos := py*width + px
ppos := ppy*width + ppx
ppx, ppy = px, py
board[pos], board[ppos] = true, false
buf = buf[:0]
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
cell = cellEmpty
if board[y*width+x] {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
screen.MoveTopLeft()
fmt.Print(string(buf))
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/exercises/05-no-slice/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
"github.com/inancgumus/screen"
"github.com/mattn/go-runewidth"
)
func main() {
const (
cellEmpty = ' '
cellBall = '⚾'
maxFrames = 1200
speed = time.Second / 20
// initial velocities
ivx, ivy = 1, 1
)
var (
px, py int // ball position
vx, vy = ivx, ivy // velocities
cell rune // current cell (for caching)
)
width, height := screen.Size()
width /= runewidth.RuneWidth(cellBall)
height-- // there is a 1 pixel border in my terminal
// create a drawing buffer
// *2 for extra spaces
// +1 for newlines
buf := make([]rune, 0, (width*2+1)*height)
screen.Clear()
for i := 0; i < maxFrames; i++ {
// calculate the next ball position
px += vx
py += vy
// when the ball hits a border reverse its direction
if px <= 0 || px >= width-1 {
vx *= -1
}
if py <= 0 || py >= height-1 {
vy *= -1
}
buf = buf[:0]
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
cell = cellEmpty
if px == x && py == y {
cell = cellBall
}
buf = append(buf, cell, ' ')
}
buf = append(buf, '\n')
}
screen.MoveTopLeft()
fmt.Print(string(buf))
time.Sleep(speed)
}
}
================================================
FILE: 18-project-bouncing-ball/exercises/README.md
================================================
# Bouncing Ball Exercises
1. **[Find the Bug](https://github.com/inancgumus/learngo/tree/master/18-project-bouncing-ball/exercises/01-find-the-bug)**
There is a bug in the bouncing ball code. Test yourself that you really understand how the backing arrays work.
2. **[Adjust the width and height automatically](https://github.com/inancgumus/learngo/tree/master/18-project-bouncing-ball/exercises/02-width-and-height)**
In this exercise, your goal is getting the width and height of the terminal screen from your operating system (instead of setting the width and height manually).
3. **[Previous positions](https://github.com/inancgumus/learngo/tree/master/18-project-bouncing-ball/exercises/03-previous-positions)**
Let's optimize the program once more. This time you're going to optimize the clearing off the previous positions.
4. **[Use a single dimensional slice](https://github.com/inancgumus/learngo/tree/master/18-project-bouncing-ball/exercises/04-single-dimensional)**
For the board slice, instead of using a multi-dimensional slice, let's use a single-dimensional slice. In this exercise, you'll understand and deeply internalize why I've used a multi-dimensional board slice.
5. **[Don't use a slice for the board](https://github.com/inancgumus/learngo/tree/master/18-project-bouncing-ball/exercises/05-no-slice)**
Expand your horizon: Don't use a slice for the board. You only need a slice for the buffer, only that.
================================================
FILE: 19-strings-runes-bytes/01-bytes-runes-strings-basics/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
str := "hey"
bytes := []byte{104, 101, 121}
// same as: []byte("hey")
fmt.Printf(`"hey" as bytes : %d`+"\n", []byte(str))
// same as: string([]byte{104, 101, 121})
fmt.Printf("bytes as string : %q\n", string(bytes))
// runes are unicode codepoints (numbers)
fmt.Println()
fmt.Printf("%c : %[1]d\n", 'h')
fmt.Printf("%c : %[1]d\n", 'e')
fmt.Printf("%c : %[1]d\n", 'y')
// a rune literal is typeless
// you can put it in any numeric type
var (
anInt int = 'h'
anInt8 int8 = 'h'
anInt16 int16 = 'h'
anInt32 int32 = 'h'
// rune literal's default type is: rune
// so, you don't need to specify it.
// aRune rune = 'h'
aRune = 'h'
// and so on...
)
fmt.Println()
fmt.Printf("rune literals are typeless:\n\t%T %T %T %T %T\n",
anInt, anInt8, anInt16, anInt32, aRune)
fmt.Println()
// all are the same rune
// beginning with go 1.13 you can type: 0b0110_1000 instead
// fmt.Printf("%q as binary: %08[1]b\n", 0b0110_1000)
fmt.Printf("%q in decimal: %[1]d\n", 104)
fmt.Printf("%q in binary : %08[1]b\n", 'h')
fmt.Printf("%q in hex : 0x%[1]x\n", 0x68)
}
================================================
FILE: 19-strings-runes-bytes/02-bytes-runes-strings-charset-table/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
func main() {
var start, stop int
if args := os.Args[1:]; len(args) == 2 {
start, _ = strconv.Atoi(args[0])
stop, _ = strconv.Atoi(args[1])
}
if start == 0 || stop == 0 {
start, stop = 'A', 'Z'
}
fmt.Printf("%-10s %-10s %-10s %-12s\n%s\n",
"literal", "dec", "hex", "encoded",
strings.Repeat("-", 45))
for n := start; n <= stop; n++ {
fmt.Printf("%-10c %-10[1]d %-10[1]x % -12x\n", n, string(n))
}
}
/*
EXAMPLE UNICODE BLOCKS
1 byte
------------------------------------------------------------
asciiStart = '\u0001' -> 32
asciiStop = '\u007f' -> 127
upperCaseStart = '\u0041' -> 65
upperCaseStop = '\u005a' -> 90
lowerCaseStart = '\u0061' -> 97
lowerCaseStop = '\u007a' -> 122
2 bytes
------------------------------------------------------------
latin1Start = '\u0080' -> 161
latin1Stop = '\u00ff' -> 255
3 bytes
------------------------------------------------------------
dingbatStart = '\u2700' -> 9984
dingbatStop = '\u27bf' -> 10175
4 bytes
------------------------------------------------------------
emojiStart = '\U0001f600' -> 128512
emojiStop = '\U0001f64f' -> 128591
*/
================================================
FILE: 19-strings-runes-bytes/03-bytes-runes-strings-examples/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"unicode/utf8"
"unsafe"
)
func main() {
str := "Yūgen ☯ 💀"
// can't change a string
// a string is a read-only byte-slice
// str[0] = 'N'
// str[1] = 'o'
bytes := []byte(str)
// can change a byte slice
// bytes[0] = 'N'
// bytes[1] = 'o'
str = string(bytes)
fmt.Printf("%s\n", str)
fmt.Printf("\t%d bytes\n", len(str))
fmt.Printf("\t%d runes\n", utf8.RuneCountInString(str))
fmt.Printf("% x\n", bytes)
fmt.Printf("\t%d bytes\n", len(bytes))
fmt.Printf("\t%d runes\n", utf8.RuneCount(bytes))
// fmt.Println()
// for i, r := range str {
// fmt.Printf("str[%2d] = % -12x = %q\n", i, string(r), r)
// }
fmt.Println()
fmt.Printf("1st byte : %c\n", str[0]) // ok
fmt.Printf("2nd byte : %c\n", str[1]) // not ok
fmt.Printf("2nd rune : %s\n", str[1:3]) // ok
fmt.Printf("last rune : %s\n", str[len(str)-4:]) // ok
// disadvantage: each one is 4 bytes
runes := []rune(str)
fmt.Println()
fmt.Printf("%s\n", str)
fmt.Printf("\t%d bytes\n", int(unsafe.Sizeof(runes[0]))*len(runes))
fmt.Printf("\t%d runes\n", len(runes))
fmt.Printf("1st rune : %c\n", runes[0])
fmt.Printf("2nd rune : %c\n", runes[1])
fmt.Printf("first five : %c\n", runes[:5])
fmt.Println()
word := "öykü"
fmt.Printf("%q in runes: %c\n", word, []rune(word))
fmt.Printf("%q in bytes: % [1]x\n", word)
fmt.Printf("%s %s\n", word[:2], []byte{word[0], word[1]}) // ö
fmt.Printf("%c\n", word[2]) // y
fmt.Printf("%c\n", word[3]) // k
fmt.Printf("%s %s\n", word[4:], []byte{word[4], word[5]}) // ü
}
================================================
FILE: 19-strings-runes-bytes/04-rune-decoding/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
const text = `Galaksinin Batı Sarmal Kolu'nun bir ucunda, haritası bile çıkarılmamış ücra bir köşede, gözlerden uzak, küçük ve sarı bir güneş vardır.
Bu güneşin yörüngesinde, kabaca yüz kırksekiz milyon kilometre uzağında, tamamıyla önemsiz ve mavi-yeşil renkli, küçük bir gezegen döner.
Gezegenin maymun soyundan gelen canlıları öyle ilkeldir ki dijital kol saatinin hâlâ çok etkileyici bir buluş olduğunu düşünürler.`
r, size := utf8.DecodeRuneInString("öykü")
fmt.Printf("rune: %c size: %d bytes.\n", r, size)
r, size = utf8.DecodeRuneInString("ykü")
fmt.Printf("rune: %c size: %d bytes.\n", r, size)
r, size = utf8.DecodeRuneInString("kü")
fmt.Printf("rune: %c size: %d bytes.\n", r, size)
r, size = utf8.DecodeRuneInString("ü")
fmt.Printf("rune: %c size: %d bytes.\n", r, size)
// for range loop automatically decodes the runes
// but it gives you the position of the current rune
// instead of its size.
// for _, r := range text {}
for i := 0; i < len(text); {
r, size := utf8.DecodeRuneInString(text[i:])
fmt.Printf("%c", r)
i += size
}
fmt.Println()
}
================================================
FILE: 19-strings-runes-bytes/04-rune-decoding/02/benchmarks/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"fmt"
"testing"
"unicode"
"unicode/utf8"
)
/*
Let's run this program to see the speed differences.
benchDecoder 30000000 46.2 ns/op --> BEST
benchForRange 30000000 53.0 ns/op --> MEDIOCRE
benchConcater 20000000 93.7 ns/op --> WORST
*/
var word = []byte("öykü")
func decoder(w []byte) {
_, size := utf8.DecodeRune(word)
copy(w[:size], bytes.ToUpper(w[:size]))
}
func forRange(w []byte) {
var size int
for i := range string(w) {
if i > 0 {
size = i
break
}
}
copy(w[:size], bytes.ToUpper(w[:size]))
}
var globalString string
func concater(w []byte) {
runes := []rune(string(w))
runes[0] = unicode.ToUpper(runes[0])
globalString = string(runes)
}
func bench(technique func([]byte)) testing.BenchmarkResult {
return testing.Benchmark(func(b *testing.B) {
for i := 0; i < b.N; i++ {
technique(word)
}
})
}
func main() {
fmt.Println("benchDecoder", bench(decoder))
fmt.Println("benchForRange", bench(forRange))
fmt.Println("benchConcater", bench(concater))
}
================================================
FILE: 19-strings-runes-bytes/04-rune-decoding/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"fmt"
"unicode/utf8"
)
func main() {
word := []byte("öykü")
fmt.Printf("%s = % [1]x\n", word)
// how to make the first rune uppercase?
// you need to find the starting and ending position of the first rune
// 1st way: `for range`
// you can't get the runes by ranging over a byte slice
// first, you need to convert it to a string
var size int
for i := range string(word) {
if i > 0 {
size = i
break
}
}
// 2nd way: let's do it using the utf8 package's DecodeRune function
_, size = utf8.DecodeRune(word)
// overwrite the current bytes with the new uppercased bytes
copy(word[:size], bytes.ToUpper(word[:size]))
// to get printed bytes/runes need to be encoded in a string
fmt.Printf("%s = % [1]x\n", word)
}
================================================
FILE: 19-strings-runes-bytes/05-internals/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"unsafe"
)
func main() {
// empty := ""
// dump(empty)
hello := "hello"
dump(hello)
dump("hello")
dump("hello!")
for i := range hello {
dump(hello[i : i+1])
}
dump(string([]byte(hello)))
dump(string([]byte(hello)))
dump(string([]rune(hello)))
}
// StringHeader is used by a string value
// In practice, you should use: reflect.Header
type StringHeader struct {
// points to a backing array's item
pointer uintptr // where it starts
length int // where it ends
}
// dump prints the string header of a string value
func dump(s string) {
ptr := *(*StringHeader)(unsafe.Pointer(&s))
fmt.Printf("%q: %+v\n", s, ptr)
}
================================================
FILE: 19-strings-runes-bytes/exercises/01-convert/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Convert the strings
//
// 1. Loop over the words slice
//
// 2. In the loop:
// 1. Convert each string value to a byte slice
// 2. Print the byte slice
// 3. Append the byte slice to the `bwords`
//
// 3. Print the words using the `bwords`
//
// EXPECTED OUTPUT
// [103 111 112 104 101 114]
// [112 114 111 103 114 97 109 109 101 114]
// [103 111 32 108 97 110 103 117 97 103 101]
// [103 111 32 115 116 97 110 100 97 114 100 32 108 105 98 114 97 114 121]
// gopher
// programmer
// go language
// go standard library
// ---------------------------------------------------------
func main() {
// Please uncomment the code below
// words := []string{
// "gopher",
// "programmer",
// "go language",
// "go standard library",
// }
// var bwords [][]byte
}
================================================
FILE: 19-strings-runes-bytes/exercises/01-convert/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
words := []string{
"gopher",
"programmer",
"go language",
"go standard library",
}
var bwords [][]byte
for _, w := range words {
bw := []byte(w)
fmt.Println(bw)
bwords = append(bwords, bw)
}
for _, w := range bwords {
fmt.Println(string(w))
}
}
================================================
FILE: 19-strings-runes-bytes/exercises/02-print-the-runes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Print the runes
//
// 1. Loop over the "console" word and print its runes one by one,
// in decimals, hexadecimals and binary.
//
// 2. Manually put the runes of the "console" word to a byte slice, one by one.
//
// As the elements of the byte slice use only the rune literals.
//
// Print the byte slice.
//
// 3. Repeat the step 2 but this time, as the elements of the byte slice,
// use only decimal numbers.
//
// 4. Repeat the step 2 but this time, as the elements of the byte slice,
// use only hexadecimal numbers.
//
//
// EXPECTED OUTPUT
// Run the solution to see the expected output.
// ---------------------------------------------------------
func main() {
const word = "console"
}
================================================
FILE: 19-strings-runes-bytes/exercises/02-print-the-runes/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
const word = "console"
for _, w := range word {
fmt.Printf("%c\n", w)
fmt.Printf("\tdecimal: %[1]d\n", w)
fmt.Printf("\thex : 0x%[1]x\n", w)
fmt.Printf("\tbinary : 0b%08[1]b\n", w)
}
// print the word manually using runes
fmt.Printf("with runes : %s\n",
string([]byte{'c', 'o', 'n', 's', 'o', 'l', 'e'}))
// print the word manually using decimals
fmt.Printf("with decimals : %s\n",
string([]byte{99, 111, 110, 115, 111, 108, 101}))
// print the word manually using hexadecimals
fmt.Printf("with hexadecimals: %s\n",
string([]byte{0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65}))
}
================================================
FILE: 19-strings-runes-bytes/exercises/03-rune-manipulator/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Rune Manipulator
//
// Please read the comments inside the following code.
//
// EXPECTED OUTPUT
// Please run the solution.
// ---------------------------------------------------------
func main() {
words := []string{
"cool",
"güzel",
"jīntiān",
"今天",
"read 🤓",
}
_ = words
// Print the byte and rune length of the strings
// Hint: Use len and utf8.RuneCountInString
// Print the bytes of the strings in hexadecimal
// Hint: Use % x verb
// Print the runes of the strings in hexadecimal
// Hint: Use % x verb
// Print the runes of the strings as rune literals
// Hint: Use for range
// Print the first rune and its byte size of the strings
// Hint: Use utf8.DecodeRuneInString
// Print the last rune of the strings
// Hint: Use utf8.DecodeLastRuneInString
// Slice and print the first two runes of the strings
// Slice and print the last two runes of the strings
// Convert the string to []rune
// Print the first and last two runes
}
================================================
FILE: 19-strings-runes-bytes/exercises/03-rune-manipulator/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
words := []string{
"cool",
"güzel",
"jīntiān",
"今天",
"read 🤓",
}
for _, s := range words {
fmt.Printf("%q\n", s)
// Print the byte and rune length of the strings
// Hint: Use len and utf8.RuneCountInString
fmt.Printf("\thas %d bytes and %d runes\n",
len(s), utf8.RuneCountInString(s))
// Print the bytes of the strings in hexadecimal
// Hint: Use % x verb
fmt.Printf("\tbytes : % x\n", s)
// Print the runes of the strings in hexadecimal
// Hint: Use % x verb
fmt.Print("\trunes :")
for _, r := range s {
fmt.Printf("% x", r)
}
fmt.Println()
// Print the runes of the strings as rune literals
// Hint: Use for range
fmt.Print("\trunes :")
for _, r := range s {
fmt.Printf("%q", r)
}
fmt.Println()
// Print the first rune and its byte size of the strings
// Hint: Use utf8.DecodeRuneInString
r, size := utf8.DecodeRuneInString(s)
fmt.Printf("\tfirst : %q (%d bytes)\n", r, size)
// Print the last rune of the strings
// Hint: Use utf8.DecodeLastRuneInString
r, size = utf8.DecodeLastRuneInString(s)
fmt.Printf("\tlast : %q (%d bytes)\n", r, size)
// Slice and print the first two runes of the strings
_, first := utf8.DecodeRuneInString(s)
_, second := utf8.DecodeRuneInString(s[first:])
fmt.Printf("\tfirst 2 : %q\n", s[:first+second])
// Slice and print the last two runes of the strings
_, last1 := utf8.DecodeLastRuneInString(s)
_, last2 := utf8.DecodeLastRuneInString(s[:len(s)-last1])
fmt.Printf("\tlast 2 : %q\n", s[len(s)-last2-last1:])
// Convert the string to []rune
// Print the first and last two runes
rs := []rune(s)
fmt.Printf("\tfirst 2 : %q\n", string(rs[:2]))
fmt.Printf("\tlast 2 : %q\n", string(rs[len(rs)-2:]))
}
}
================================================
FILE: 19-strings-runes-bytes/exercises/README.md
================================================
# Strings, bytes, and runes exercises
1. **[Convert](https://github.com/inancgumus/learngo/tree/master/19-strings-runes-bytes/exercises/01-convert)**
Use []byte <-> string conversions.
2. **[Print the Runes](https://github.com/inancgumus/learngo/tree/master/19-strings-runes-bytes/exercises/02-print-the-runes)**
Use Printf verbs.
3. **[Rune Manipulator](https://github.com/inancgumus/learngo/tree/master/19-strings-runes-bytes/exercises/03-rune-manipulator)**
Use utf8 package, indexing and slicing.
================================================
FILE: 19-strings-runes-bytes/questions/README.md
================================================
# Strings, Runes and Bytes Quiz
## Which byte slice below equals to the "keeper" string?
```go
// Here are the corresponding code points for the runes of "keeper":
// k => 107
// e => 101
// p => 112
// r => 114
```
1. []byte{107, 101, 101, 112, 101, 114} *CORRECT*
2. []byte{112, 101, 101, 112, 114, 101}
3. []byte{114, 101, 112, 101, 101, 112}
4. []byte{112, 101, 101, 114, 107, 101}
## What does this code print?
```go
// Code points:
// g => 103
// o => 111
fmt.Println(string(103), string(111))
```
1. 103 111
2. g o *CORRECT*
3. n o
4. "103 111"
## What does this code print?
```go
const word = "gökyüzü"
bword := []byte(word)
// ö => 2 bytes
// ü => 2 bytes
fmt.Println(utf8.RuneCount(bword), len(word), len(string(word[1])))
```
1. 7 10 2 *CORRECT*
2. 10 7 1
3. 10 7 2
4. 7 7 1
## Which one below is true?
1. for range loops over the bytes of a string
2. for range loops over the runes of a string *CORRECT*
## For a utf-8 encoded string value, which one below is true?
1. runes always start and end in the same indexes
2. runes may start and end in different indexes *CORRECT*
3. bytes may start and end in different indexes
## Why can't you change the bytes of a string value?
1. Strings values are immutable byte slices
2. Strings are used a lot so they are being shared behind the scenes
3. All of above *CORRECT*
================================================
FILE: 20-project-spam-masker/01-step-1/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
/*
✅ #1- Get and check the input
✅ #2- Create a byte buffer and use it as the output
✅ #3- Write input to the buffer as it is and print it
✅ #4- Detect the link
#5- Mask the link
#6- Stop masking when whitespace is detected
#7- Put a http:// prefix in front of the masked link
*/
package main
import (
"fmt"
"os"
)
func main() {
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("gimme somethin' to mask!")
return
}
const (
link = "http://"
nlink = len(link)
)
var (
text = args[0]
size = len(text)
buf = make([]byte, 0, size)
)
for i := 0; i < size; i++ {
buf = append(buf, text[i])
// slice the input and look for the link pattern
// do not slice it when it goes beyond the input text's capacity
if len(text[i:]) >= nlink && text[i:i+nlink] == link {
}
}
// print out the buffer as text (string)
fmt.Println(string(buf))
}
================================================
FILE: 20-project-spam-masker/01-step-1/spam.txt
================================================
Hi guys,
Here is my new spammy webpage http://www.mysuperpage.com <-- This is my website!
Please click on the link now!!!
When you click, I will be rich, thanks!
================================================
FILE: 20-project-spam-masker/02-step-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
/*
✅ #1- Get and check the input
✅ #2- Create a byte buffer and use it as the output
✅ #3- Write input to the buffer as it is and print it
✅ #4- Detect the link
✅ #5- Mask the link
✅ #6- Stop masking when whitespace is detected
✅ #7- Put a http:// prefix in front of the masked link
*/
package main
import (
"fmt"
"os"
)
const (
link = "http://"
nlink = len(link)
mask = '*'
)
func main() {
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("gimme somethin' to mask!")
return
}
var (
text = args[0]
size = len(text)
buf = make([]byte, 0, size)
in bool
)
for i := 0; i < size; i++ {
// slice the input and look for the link pattern
// do not slice it when it goes beyond the input text's capacity
if len(text[i:]) >= nlink && text[i:i+nlink] == link {
// set the flag: we're in a link! -> "http://....."
in = true
// add the "http://" manually
buf = append(buf, link...)
// jump to the next character after "http://"
i += nlink
}
// get the current byte from the input
c := text[i]
// disable the link detection flag
// this will prevent masking the rest of the bytes
switch c {
case ' ', '\t', '\n': // try -> unicode.IsSpace
in = false
}
// if we're in the link detection mode (inside the link bytes)
// then, mask the current character
if in {
c = mask
}
buf = append(buf, c)
}
// print out the buffer as text (string)
fmt.Println(string(buf))
}
================================================
FILE: 20-project-spam-masker/02-step-2/spam.txt
================================================
Hi guys,
Here is my new spammy webpage http://www.mysuperpage.com <-- This is my website!
Please click on the link now!!!
When you click, I will be rich, thanks!
================================================
FILE: 20-project-spam-masker/03-step-2-no-append/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
/*
✅ #1- Get and check the input
✅ #2- Create a byte buffer and use it as the output
✅ #3- Write input to the buffer as it is and print it
✅ #4- Detect the link
✅ #5- Mask the link
✅ #6- Stop masking when whitespace is detected
✅ #7- Put a http:// prefix in front of the masked link
*/
package main
import (
"fmt"
"os"
)
const (
link = "http://"
nlink = len(link)
mask = '*'
)
func main() {
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("gimme somethin' to mask!")
return
}
var (
text = args[0]
size = len(text)
// create a byte buffer directly from the string (text)
buf = []byte(text)
in bool
)
for i := 0; i < size; i++ {
// no need to add an artificial http:// prefix
// it's already there
if len(text[i:]) >= nlink && text[i:i+nlink] == link {
in = true
i += nlink
}
switch text[i] {
case ' ', '\t', '\n': // try -> unicode.IsSpace
in = false
}
// when censoring mode: on
// directly manipulate the bytes on the buffer
if in {
buf[i] = mask
}
}
fmt.Println(string(buf))
}
================================================
FILE: 20-project-spam-masker/03-step-2-no-append/spam.txt
================================================
Hi guys,
Here is my new spammy webpage http://www.mysuperpage.com <-- This is my website!
Please click on the link now!!!
When you click, I will be rich, thanks!
================================================
FILE: 20-project-spam-masker/README.md
================================================
# Spam Masker Challenge Tips
## Rules:
* You shouldn't use a standard library function.
* You should only solve the challenge by manipulating the bytes directly.
* Manipulate the bytes of a string using indexing, slicing, appending etc.
* Be efficient: Do not use string concat (+ operator).
* Instead, create a new byte slice as a buffer from the given string argument.
* Then, manipulate it during your program.
* And, for once, print that buffer.
* Mask only links starting with `http://`
* Don't check for uppercase/lowercase letters
* The goal is learning how to manipulate bytes in strings, it's not about creating the perfect masker.
* For example: A spammer can prevent the masker like this (for now this is OK):
```
"Here's my spammy page: hTTp://youth-elixir.com"
^^
```
* But, you should catch this:
```
INPUT:
Here's my spammy page: http://hehefouls.netHAHAHA see you.
OUTPUT:
Here's my spammy page: http://******************* see you.
```
## Steps:
1. Check whether there's a command line argument or not. If not, quit from the program with a message.
2. Create a byte buffer as big as the argument.
3. Loop and detect the `http://` patterns
4. Copy the input character by character to the buffer
5. If you detect `http://` pattern, copy the `http://` first, then copy the `*`s instead of the original link until you see whitespace character.
For example:
```
INPUT:
Here: http://www.mylink.com Click!
OUTPUT:
Here: http://************** Click!
```
6. Print the buffer as a string
================================================
FILE: 21-project-text-wrapper/README.md
================================================
# Text Wrapper Challenge Guideline
In this project your goal is to mimic the soft text wrapping feature of text editors. For example, when there are 100 characters on a line and if the soft-wrapping is set to 40, an editor may cut the line that goes beyond 40 characters and display the rest of the line in the next line instead.
## EXAMPLE
Wrap the given text for 40 characters per line. For example, for the following input, the program should print the following output.
**INPUT:**
Hello world, how is it going? It is ok.. The weather is beautiful.
**OUTPUT:**
Hello world, how is it going? It is ok..
The weather is beautiful.
## RULES
* The program should work with Unicode text. You can find a unicode text in [story.txt](story.txt) file.
* The program should not cut the words before they finish. Instead, it should put the whole word on the next line.
For example, this is not OK:
Hello world, how is it goi
ng? It is o
k. The weather is beautifu
l.
## SOLUTION
* [Get the solution source code here](main.go).
================================================
FILE: 21-project-text-wrapper/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"unicode"
)
func main() {
const text = `Galaksinin Batı Sarmal Kolu'nun bir ucunda, haritası bile çıkarılmamış ücra bir köşede, gözlerden uzak, küçük ve sarı bir güneş vardır.
Bu güneşin yörüngesinde, kabaca yüz kırksekiz milyon kilometre uzağında, tamamıyla önemsiz ve mavi-yeşil renkli, küçük bir gezegen döner.
Gezegenin maymun soyundan gelen canlıları öyle ilkeldir ki dijital kol saatinin hâlâ çok etkileyici bir buluş olduğunu düşünürler.`
const maxWidth = 40
var lw int // line width
for _, r := range text {
fmt.Printf("%c", r)
switch lw++; {
case lw > maxWidth && r != '\n' && unicode.IsSpace(r):
fmt.Println()
fallthrough
case r == '\n':
lw = 0
}
}
fmt.Println()
}
================================================
FILE: 21-project-text-wrapper/story.txt
================================================
Galaksinin Batı Sarmal Kolu'nun bir ucunda, haritası bile çıkarılmamış ücra bir köşede, gözlerden uzak, küçük ve sarı bir güneş vardır.
Bu güneşin yörüngesinde, kabaca yüz kırksekiz milyon kilometre uzağında, tamamıyla önemsiz ve mavi-yeşil renkli, küçük bir gezegen döner.
Gezegenin maymun soyundan gelen canlıları öyle ilkeldir ki dijital kol saatinin hâlâ çok etkileyici bir buluş olduğunu düşünürler.
================================================
FILE: 22-maps/01-english-dict/01-as-a-slice/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("[english word] -> [turkish word]")
return
}
query := args[0]
english := []string{"good", "great", "perfect"}
turkish := []string{"iyi", "harika", "mükemmel"}
// O(n) -> Inefficient: Depends on 'n'.
for i, w := range english {
if query == w {
fmt.Printf("%q means %q\n", w, turkish[i])
return
}
}
fmt.Printf("%q not found\n", query)
}
================================================
FILE: 22-maps/01-english-dict/02-as-a-map/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
// args := os.Args[1:]
// if len(args) != 1 {
// fmt.Println("[english word] -> [turkish word]")
// return
// }
// query := args[0]
// #1: Nil Map: Read-Only
var dict map[string]string
// #5: You cannot assign to a nil map.
// dict["up"] = "yukarı"
// dict["down"] = "aşağı"
// #2: Map retrieval is O(1) — on average.
key := "good"
value := dict[key]
fmt.Printf("%q means %#v\n", key, value)
// #1B
fmt.Printf("# of Keys: %d\n", len(dict))
// fmt.Printf("Zero Value: %#v\n", dict)
// #4: Nil map ready to use
// if dict != nil {
// value := dict[key]
// fmt.Printf("%q means %#v\n", key, value)
// }
// #3: Cannot use non-comparable types as map key types
// var broken map[[]int]int
// var broken map[map[int]string]bool
//
// A map can only be compared to nil value
// _ = dict == nil
}
================================================
FILE: 22-maps/02-english-dict-map-populate/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
// #2A: Get the key from CLI
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("[english word] -> [turkish word]")
return
}
query := args[0]
// #1: Empty Map Literal
// dict := map[string]string{}
// 3: Map Literal
dict := map[string]string{
"good": "kötü",
"great": "harika",
"perfect": "mükemmel",
// #4
// 42: "forty two",
// "forty two": 42,
}
dict["up"] = "yukarı" // adds a new pair
dict["down"] = "aşağı" // adds a new pair
dict["good"] = "iyi" // #5: overwrites the value at the key: "good"
dict["mistake"] = "" // #8: a key with a zero-value
// #10: comma ok in a short if
if value, ok := dict[query]; ok {
fmt.Printf("%q means %#v\n", query, value)
return
}
fmt.Printf("%q not found.\n", query)
// fmt.Printf("Zero Value: %#v\n", dict)
fmt.Printf("# of Keys : %d\n", len(dict))
// #13: compare a map using its printed output
// copied := map[string]string{"up": "yukarı", "down": "aşağı",
// "mistake": "", "good": "iyi", "great": "harika",
// "perfect": "mükemmel"}
// first := fmt.Sprintf("%s", dict)
// second := fmt.Sprintf("%s", copied)
// if first == second {
// fmt.Println("Maps are equal")
// }
// #12: printing a map (ordered output since Go 1.12)
// fmt.Printf("%#v\n", dict)
// #11
// for k, v := range dict {
// fmt.Printf("%q means %#v\n", k, v)
// }
// #9: check for non-existing key: with comma, ok
// value, ok := dict[query]
// if !ok {
// fmt.Printf("%q not found.\n", query)
// }
// #7: check for non-existing key using zero-value
// if value == "" {
// fmt.Printf("%q not found.\n", query)
// }
// #6: getting values from a map using keys directly
// fmt.Println("good -> ", dict["good"])
// fmt.Println("great -> ", dict["great"])
// fmt.Println("perfect -> ", dict["perfect"])
// #2B: retrieve values by key - O(1) efficiency
// value := dict[query]
}
================================================
FILE: 22-maps/03-internals-cloning/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("[english word] -> [turkish word]")
return
}
query := args[0]
dict := map[string]string{
"good": "iyi",
"great": "harika",
"perfect": "mükemmel",
"awesome": "mükemmel", // #5
}
// turkish := dict // #1
// turkish["good"] = "güzel"
// dict["great"] = "kusursuz"
delete(dict, "awesome") // #6
delete(dict, "awesome") // #7: no-op
delete(dict, "notexisting")
// dict = nil // #8
for k := range dict { // #9
delete(dict, k)
}
// turkish := make(map[string]string) // #2
turkish := make(map[string]string, len(dict)) // #3
for k, v := range dict {
turkish[v] = k
}
// fmt.Printf("english: %q\nturkish: %q\n", dict, turkish) // #4
if value, ok := dict[query]; ok {
fmt.Printf("%q means %#v\n", query, value)
return
}
if value, ok := turkish[query]; ok {
fmt.Printf("%q means %#v\n", query, value)
return
}
fmt.Printf("%q not found.\n", query)
}
================================================
FILE: 22-maps/exercises/01-warm-up/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Warm-up
//
// Create and print the following maps.
//
// 1. Phone numbers by last name
// 2. Product availability by Product ID
// 3. Multiple phone numbers by last name
// 4. Shopping basket by Customer ID
//
// Each item in the shopping basket has a Product ID and
// quantity. Through the map, you can tell:
// "Mr. X has bought Y bananas"
//
// ---------------------------------------------------------
func main() {
// Hint: Store phone numbers as text
// #1
// Key : Last name
// Element : Phone number
// #2
// Key : Product ID
// Element : Available / Unavailable
// #3
// Key : Last name
// Element : Phone numbers
// #4
// Key : Customer ID
// Element Key:
// Key: Product ID Element: Quantity
}
================================================
FILE: 22-maps/exercises/01-warm-up/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
phones map[string]string
// Key : Last name
// Element : Phone number
// Key : Product ID
// Element : Available / Unavailable
products map[int]bool
multiPhones map[string][]string
// Key : Last name
// Element : Phone numbers
basket map[int]map[int]int
// Key : Customer ID
// Element Key:
// Key: Product ID Element: Quantity
)
fmt.Printf("phones : %#v\n", phones)
fmt.Printf("products : %#v\n", products)
fmt.Printf("multiPhones: %#v\n", multiPhones)
fmt.Printf("basket : %#v\n", basket)
}
================================================
FILE: 22-maps/exercises/02-populate/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Populate and Lookup
//
// Add elements to the maps that you've declared in the
// first exercise, and try them by looking up for the keys.
//
// Either use the `make()` or `map literals`.
//
// After completing the exercise, remove the data and check
// that your program still works.
//
//
// 1. Phone numbers by last name
// --------------------------
// bowen 202-555-0179
// dulin 03.37.77.63.06
// greco 03489940240
//
// Print the dulin's phone number.
//
//
// 2. Product availability by Product ID
// ----------------
// 617841573 true
// 879401371 false
// 576872813 true
//
// Is Product ID 879401371 available?
//
//
// 3. Multiple phone numbers by last name
// ------------------------------------------------------
// bowen [202-555-0179]
// dulin [03.37.77.63.06 03.37.70.50.05 02.20.40.10.04]
// greco [03489940240 03489900120]
//
// What is Greco's second phone number?
//
//
// 4. Shopping basket by Customer ID
// -------------------------------
// 100 [617841573:4 576872813:2]
// 101 [576872813:5 657473833:20]
// 102 []
//
// How many of 576872813 the customer 101 is going to buy?
// (Product ID) (Customer ID)
//
//
// EXPECTED OUTPUT
//
// 1. Run the solution to see the output
// 2. Here is the output with empty maps:
//
// dulin's phone number: N/A
// Product ID #879401371 is not available
// greco's 2nd phone number: N/A
// Customer #101 is going to buy 5 from Product ID #576872813.
//
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 22-maps/exercises/02-populate/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
phones := map[string]string{
"bowen": "202-555-0179",
"dulin": "03.37.77.63.06",
"greco": "03489940240",
}
products := map[int]bool{
617841573: true,
879401371: false,
576872813: true,
}
multiPhones := map[string][]string{
"bowen": {"202-555-0179"},
"dulin": {"03.37.77.63.06", "03.37.70.50.05", "02.20.40.10.04"},
"greco": {"03489940240", "03489900120"},
}
basket := map[int]map[int]int{
100: {617841573: 4, 576872813: 2},
101: {576872813: 5, 657473833: 20},
102: {},
}
// Print dulin's phone number.
who, phone := "dulin", "N/A"
if v, ok := phones[who]; ok {
phone = v
}
fmt.Printf("%s's phone number: %s\n", who, phone)
// Is Product ID 879401371 available?
id, status := 879401371, "available"
if !products[id] {
status = "not " + status
}
fmt.Printf("Product ID #%d is %s\n", id, status)
// What is Greco's second phone number?
who, phone = "greco", "N/A"
if phones := multiPhones[who]; len(phones) >= 2 {
phone = phones[1]
}
fmt.Printf("%s's 2nd phone number: %s\n", who, phone)
// How many of 576872813 the customer 101 is going to buy?
cid, pid := 101, 576872813
fmt.Printf("Customer #%d is going to buy %d from Product ID #%d.\n", cid, basket[cid][pid], pid)
}
================================================
FILE: 22-maps/exercises/03-students/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Students
//
// Create a program that returns the students by the given
// Hogwarts house name (see the data below).
//
// Print the students sorted by name.
//
// "bobo" doesn't belong to Hogwarts, remove it by using
// the delete function.
//
//
// RESTRICTIONS
//
// + Add the following data to your map as is.
// Do not sort it manually and do not modify it.
//
// + Slices in the map shouldn't be sorted (changed).
// HINT: Copy them.
//
//
// EXPECTED OUTPUT
//
// go run main.go
//
// Please type a Hogwarts house name.
//
//
// go run main.go bobo
//
// Sorry. I don't know anything about "bobo".
//
//
// go run main.go hufflepuf
//
// ~~~ hufflepuf students ~~~
//
// + diggory
// + helga
// + scamander
// + wenlock
//
// ---------------------------------------------------------
func main() {
// House Student Name
// ---------------------------
// gryffindor weasley
// gryffindor hagrid
// gryffindor dumbledore
// gryffindor lupin
// hufflepuf wenlock
// hufflepuf scamander
// hufflepuf helga
// hufflepuf diggory
// ravenclaw flitwick
// ravenclaw bagnold
// ravenclaw wildsmith
// ravenclaw montmorency
// slytherin horace
// slytherin nigellus
// slytherin higgs
// slytherin scorpius
// bobo wizardry
// bobo unwanted
}
================================================
FILE: 22-maps/exercises/03-students/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"sort"
)
func main() {
houses := map[string][]string{
"gryffindor": {"weasley", "hagrid", "dumbledore", "lupin"},
"hufflepuf": {"wenlock", "scamander", "helga", "diggory", "bobo"},
"ravenclaw": {"flitwick", "bagnold", "wildsmith", "montmorency"},
"slytherin": {"horace", "nigellus", "higgs", "bobo", "scorpius"},
"bobo": {"wizardry", "unwanted"},
}
// remove the "bobo" house
delete(houses, "bobo")
args := os.Args[1:]
if len(args) < 1 {
fmt.Println("Please type a Hogwarts house name.")
return
}
house, students := args[0], houses[args[0]]
if students == nil {
fmt.Printf("Sorry. I don't know anything about %q.\n", house)
return
}
// only sort the clone
clone := append([]string(nil), students...)
sort.Strings(clone)
fmt.Printf("~~~ %s students ~~~\n\n", house)
for _, student := range clone {
fmt.Printf("\t+ %s\n", student)
}
}
================================================
FILE: 22-maps/exercises/README.md
================================================
# Header
What you will learn?
1. **[Warm Up](https://github.com/inancgumus/learngo/tree/master/22-maps/exercises/01-warm-up)**
Create and print the maps.
2. **[Populate and Lookup](https://github.com/inancgumus/learngo/tree/master/22-maps/exercises/02-populate)**
Add elements to the maps that you've declared in the first exercise, and try them by looking up for the keys.
3. **[Hogwarts Students](https://github.com/inancgumus/learngo/tree/master/22-maps/exercises/03-students)**
Create a program that returns the students by the given Hogwarts house name.
================================================
FILE: 22-maps/questions/README.md
================================================
## Why are maps used for?
For example, here is an inefficient program that uses a loop to find an element among millions of elements.
```go
millions := []int{/* millions of elements */}
for _, v := range millions {
if v == userQuery {
// do something
}
}
```
1. Maps allow fast-lookup for map keys in O(1) time *CORRECT*
2. Maps allow fast-lookup for map keys in O(n) time
3. Maps allow fast-traversal on map keys in O(1) time
> **1:** That's right. Maps work in O(1) in average for fast-lookup.
>
> **2:** Map doesn't work in O(n) time for key lookup.
>
## When should you not use a map?
1. To find an element through a key
2. To loop over the map keys *CORRECT*
3. To add structured data to your program
> **1:** That is when you use a map.
>
> **2:** Right! Looping over map keys happen in O(n) time. So, maps are the worst data structures for key traversing.
>
> **3:** Maps don't allow you to add structured data to your program.
## Which type below cannot be a map key?
1. map[string]int
2. []string
3. []int
4. []bool
5. All of them *CORRECT*
> **5:** Slices, maps, and function values are not comparable. So, they cannot be map keys.
>
## Which are the key and element types of the map below?
```go
map[string]map[int]bool
```
1. Key: string Element: bool
2. Key: string Element: int
3. Key: string Element: map[int]
4. Key: string Element: map[int]bool *CORRECT*
> **4:** The map contains other maps. The element type of a map can be of any type.
>
## What is a map value behind the scenes?
1. A map header
2. A pointer to a map header *CORRECT*
3. Tiny data structure with 3 fields: Pointer, Length and Capacity
> **2**: That's right. Maps are complex data structures. However, each map value is only a pointer to a map header (which is a more complex data structure).
================================================
FILE: 23-input-scanning/01-scanning/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
// Simulate an error
// os.Stdin.Close()
// Create a new scanner that scans from the standard-input
in := bufio.NewScanner(os.Stdin)
// Stores the total number of lines in the input
var lines int
// Scan the input line by line
for in.Scan() {
lines++
// Get the current line from the scanner's buffer
// fmt.Println("Scanned Text :", in.Text())
// fmt.Println("Scanned Bytes:", in.Bytes())
in.Text()
}
fmt.Printf("There are %d line(s)\n", lines)
if err := in.Err(); err != nil {
fmt.Println("ERROR:", err)
}
}
================================================
FILE: 23-input-scanning/01-scanning/proverbs.txt
================================================
Go Proverbs
Make the zero value useful
Clear is better than clever
Errors are values
================================================
FILE: 23-input-scanning/02-map-as-sets/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"regexp"
"strings"
)
func main() {
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("Please type a search word.")
return
}
query := args[0]
rx := regexp.MustCompile(`[^a-z]+`)
in := bufio.NewScanner(os.Stdin)
in.Split(bufio.ScanWords)
words := make(map[string]bool)
for in.Scan() {
word := strings.ToLower(in.Text())
word = rx.ReplaceAllString(word, "")
if len(word) > 2 {
words[word] = true
}
}
// for word := range words {
// fmt.Println(word)
// }
if words[query] {
fmt.Printf("The input contains %q.\n", query)
return
}
fmt.Printf("Sorry. The input does not contain %q.\n", query)
// query := "sun"
// fmt.Println("sun:", words["sun"], "tesla:", words["tesla"])
// unnecessary
// if _, ok := words[query]; ok {
// fmt.Printf("The input contains %q.\n", query)
// return
// }
// fmt.Printf("Sorry. The input does not contain %q.\n", query)
}
================================================
FILE: 23-input-scanning/02-map-as-sets/shakespeare.txt
================================================
come night come romeo come thou day in night
for thou wilt lie upon the wings of night
whiter than new snow on a raven's back
come gentle night come loving black-browed night
give me my romeo and when he shall die
take him and cut him out in little stars
and he will make the face of heaven so fine
that all the world will be in love with night
and pay no worship to the garish sun
oh I have bought the mansion of love
but not possessed it and though I am sold
not yet enjoyed
================================================
FILE: 23-input-scanning/03-project-log-parser/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 23-input-scanning/03-project-log-parser/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 23-input-scanning/03-project-log-parser/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 23-input-scanning/03-project-log-parser/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 23-input-scanning/03-project-log-parser/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
func main() {
var (
sum map[string]int // total visits per domain
domains []string // unique domain names
total int // total visits to all domains
lines int // number of parsed lines (for the error messages)
)
sum = make(map[string]int)
// Scan the standard-in line by line
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
lines++
// Parse the fields
fields := strings.Fields(in.Text())
if len(fields) != 2 {
fmt.Printf("wrong input: %v (line #%d)\n", fields, lines)
return
}
domain := fields[0]
// Sum the total visits per domain
visits, err := strconv.Atoi(fields[1])
if visits < 0 || err != nil {
fmt.Printf("wrong input: %q (line #%d)\n", fields[1], lines)
return
}
// Collect the unique domains
if _, ok := sum[domain]; !ok {
domains = append(domains, domain)
}
// Keep track of total and per domain visits
total += visits
sum[domain] += visits
}
// Print the visits per domain
sort.Strings(domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range domains {
visits := sum[domain]
fmt.Printf("%-30s %10d\n", domain, visits)
}
// Print the total visits for all domains
fmt.Printf("\n%-30s %10d\n", "TOTAL", total)
// Let's handle the error
if err := in.Err(); err != nil {
fmt.Println("> Err:", err)
}
}
================================================
FILE: 23-input-scanning/exercises/01-uppercaser/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Uppercaser
//
// Use a scanner to convert the lines to uppercase, and
// print them.
//
// 1. Feed the shakespeare.txt to your program.
//
// 2. Scan the input using a new Scanner.
//
// 3. Print each line.
//
// EXPECTED OUTPUT
// Please run the solution to see the expected output.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 23-input-scanning/exercises/01-uppercaser/shakespeare.txt
================================================
come night come romeo come thou day in night
for thou wilt lie upon the wings of night
whiter than new snow on a raven's back
come gentle night come loving black-browed night
give me my romeo and when he shall die
take him and cut him out in little stars
and he will make the face of heaven so fine
that all the world will be in love with night
and pay no worship to the garish sun
oh I have bought the mansion of love
but not possessed it and though I am sold
not yet enjoyed
================================================
FILE: 23-input-scanning/exercises/01-uppercaser/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
fmt.Println(strings.ToUpper(in.Text()))
}
}
================================================
FILE: 23-input-scanning/exercises/01-uppercaser/solution/shakespeare.txt
================================================
come night come romeo come thou day in night
for thou wilt lie upon the wings of night
whiter than new snow on a raven's back
come gentle night come loving black-browed night
give me my romeo and when he shall die
take him and cut him out in little stars
and he will make the face of heaven so fine
that all the world will be in love with night
and pay no worship to the garish sun
oh I have bought the mansion of love
but not possessed it and though I am sold
not yet enjoyed
================================================
FILE: 23-input-scanning/exercises/02-unique-words/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Unique Words
//
// Create a program that prints the total and unique words
// from an input stream.
//
// 1. Feed the shakespeare.txt to your program.
//
// 2. Scan the input using a new Scanner.
//
// 3. Configure the scanner to scan for the words.
//
// 4. Count the unique words using a map.
//
// 5. Print the total and unique words.
//
//
// EXPECTED OUTPUT
//
// There are 99 words, 70 of them are unique.
//
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 23-input-scanning/exercises/02-unique-words/shakespeare.txt
================================================
come night come romeo come thou day in night
for thou wilt lie upon the wings of night
whiter than new snow on a raven's back
come gentle night come loving black-browed night
give me my romeo and when he shall die
take him and cut him out in little stars
and he will make the face of heaven so fine
that all the world will be in love with night
and pay no worship to the garish sun
oh I have bought the mansion of love
but not possessed it and though I am sold
not yet enjoyed
================================================
FILE: 23-input-scanning/exercises/02-unique-words/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
in := bufio.NewScanner(os.Stdin)
in.Split(bufio.ScanWords)
total, words := 0, make(map[string]int)
for in.Scan() {
total++
words[in.Text()]++
}
fmt.Printf("There are %d words, %d of them are unique.\n",
total, len(words))
}
================================================
FILE: 23-input-scanning/exercises/02-unique-words/solution/shakespeare.txt
================================================
come night come romeo come thou day in night
for thou wilt lie upon the wings of night
whiter than new snow on a raven's back
come gentle night come loving black-browed night
give me my romeo and when he shall die
take him and cut him out in little stars
and he will make the face of heaven so fine
that all the world will be in love with night
and pay no worship to the garish sun
oh I have bought the mansion of love
but not possessed it and though I am sold
not yet enjoyed
================================================
FILE: 23-input-scanning/exercises/03-unique-words-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Unique Words 2
//
// Use your solution from the previous "Unique Words"
// exercise.
//
// Before adding the words to your map, remove the
// punctuation characters and numbers from them.
//
//
// BE CAREFUL
//
// Now the shakespeare.txt contains upper and lower
// case letters too.
//
//
// EXPECTED OUTPUT
//
// go run main.go < shakespeare.txt
//
// There are 100 words, 69 of them are unique.
//
// ---------------------------------------------------------
func main() {
// This is the regular expression pattern you need to use:
// [^A-Za-z]+
//
// Matches to any character but upper case and lower case letters
}
================================================
FILE: 23-input-scanning/exercises/03-unique-words-2/shakespeare.txt
================================================
Come, night. Come, Romeo. Come, thou day in night,
For thou wilt lie upon the wings of night
Whiter than new snow upon a raven’s back.
Come, gentle night, come, loving, black-browed night,
Give me my Romeo. And when I shall die,
Take him and cut him out in little stars,
And he will make the face of heaven so fine
That all the world will be in love with night
And pay no worship to the garish sun.
Oh, I have bought the mansion of a love,
But not possessed it, and though I am sold,
Not yet enjoyed.
================================================
FILE: 23-input-scanning/exercises/03-unique-words-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"regexp"
"strings"
)
func main() {
in := bufio.NewScanner(os.Stdin)
in.Split(bufio.ScanWords)
rx := regexp.MustCompile(`[^A-Za-z]+`)
total, words := 0, make(map[string]int)
for in.Scan() {
total++
word := rx.ReplaceAllString(in.Text(), "")
word = strings.ToLower(word)
words[word]++
}
fmt.Printf("There are %d words, %d of them are unique.\n",
total, len(words))
}
================================================
FILE: 23-input-scanning/exercises/03-unique-words-2/solution/shakespeare.txt
================================================
Come, night. Come, Romeo. Come, thou day in night,
For thou wilt lie upon the wings of night
Whiter than new snow upon a raven’s back.
Come, gentle night, come, loving, black-browed night,
Give me my Romeo. And when I shall die,
Take him and cut him out in little stars,
And he will make the face of heaven so fine
That all the world will be in love with night
And pay no worship to the garish sun.
Oh, I have bought the mansion of a love,
But not possessed it, and though I am sold,
Not yet enjoyed.
================================================
FILE: 23-input-scanning/exercises/04-grep/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Grep Clone
//
// Create a grep clone. grep is a command-line utility for
// searching plain-text data for lines that match a specific
// pattern.
//
// 1. Feed the shakespeare.txt to your program.
//
// 2. Accept a command-line argument for the pattern
//
// 3. Only print the lines that contains that pattern
//
// 4. If no pattern is provided, print all the lines
//
//
// EXPECTED OUTPUT
//
// go run main.go come < shakespeare.txt
//
// come night come romeo come thou day in night
// come gentle night come loving black-browed night
//
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 23-input-scanning/exercises/04-grep/shakespeare.txt
================================================
come night come romeo come thou day in night
for thou wilt lie upon the wings of night
whiter than new snow on a raven's back
come gentle night come loving black-browed night
give me my romeo and when he shall die
take him and cut him out in little stars
and he will make the face of heaven so fine
that all the world will be in love with night
and pay no worship to the garish sun
oh I have bought the mansion of love
but not possessed it and though I am sold
not yet enjoyed
================================================
FILE: 23-input-scanning/exercises/04-grep/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
in := bufio.NewScanner(os.Stdin)
var pattern string
if args := os.Args[1:]; len(args) == 1 {
pattern = args[0]
}
for in.Scan() {
s := in.Text()
if strings.Contains(s, pattern) {
fmt.Println(s)
}
}
}
================================================
FILE: 23-input-scanning/exercises/04-grep/solution/shakespeare.txt
================================================
come night come romeo come thou day in night
for thou wilt lie upon the wings of night
whiter than new snow on a raven's back
come gentle night come loving black-browed night
give me my romeo and when he shall die
take him and cut him out in little stars
and he will make the face of heaven so fine
that all the world will be in love with night
and pay no worship to the garish sun
oh I have bought the mansion of love
but not possessed it and though I am sold
not yet enjoyed
================================================
FILE: 23-input-scanning/exercises/05-quit/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Quit
//
// Create a program that quits when a user types the
// same word twice.
//
//
// RESTRICTION
//
// The program should work case insensitive.
//
//
// EXPECTED OUTPUT
//
// go run main.go
//
// hey
// HEY
// TWICE!
//
// go run main.go
//
// hey
// hi
// HEY
// TWICE!
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 23-input-scanning/exercises/05-quit/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
in := bufio.NewScanner(os.Stdin)
words := make(map[string]bool)
for in.Scan() {
w := strings.ToLower(in.Text())
if words[w] {
fmt.Println("TWICE!")
return
}
words[in.Text()] = true
}
}
================================================
FILE: 23-input-scanning/exercises/06-log-parser/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 23-input-scanning/exercises/06-log-parser/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 23-input-scanning/exercises/06-log-parser/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 23-input-scanning/exercises/06-log-parser/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 23-input-scanning/exercises/06-log-parser/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Log Parser from Stratch
//
// You've watched the lecture. Now, try to create the same
// log parser program on your own. Do not look at the lecture,
// and the existing source code.
//
//
// EXPECTED OUTPUT
//
// go run main.go < log.txt
//
// DOMAIN VISITS
// ---------------------------------------------
// blog.golang.org 30
// golang.org 10
// learngoprogramming.com 20
//
// TOTAL 60
//
//
// go run main.go < log_err_missing.txt
//
// wrong input: [golang.org] (line #3)
//
//
// go run main.go < log_err_negative.txt
//
// wrong input: "-100" (line #3)
//
//
// go run main.go < log_err_str.txt
//
// wrong input: "FOUR" (line #3)
//
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 23-input-scanning/exercises/README.md
================================================
# Exercises
Let's exercise with the scanner and maps.
1. **[Uppercaser](https://github.com/inancgumus/learngo/tree/master/23-input-scanning/exercises/01-uppercaser)**
Use a scanner to convert the lines to uppercase, and print them.
2. **[Unique Words](https://github.com/inancgumus/learngo/tree/master/23-input-scanning/exercises/02-unique-words)**
Create a program that counts the unique words from an input stream.
3. **[Unique Words 2](https://github.com/inancgumus/learngo/tree/master/23-input-scanning/exercises/03-unique-words-2)**
Enhance the previous exercise: Before adding the words to your map, remove the punctuation characters and numbers from them.
4. **[Grep Clone](https://github.com/inancgumus/learngo/tree/master/23-input-scanning/exercises/04-grep)**
Create a grep clone. grep is a command-line utility for searching plain-text data for lines that match a specific pattern.
5. **[Quit](https://github.com/inancgumus/learngo/tree/master/23-input-scanning/exercises/05-quit)**
Create a program that quits when a user types the same word twice.
6. **[Create the Log Parser program from scratch](https://github.com/inancgumus/learngo/tree/master/23-input-scanning/exercises/06-log-parser)**
You've watched the lecture. Now, try to create the same log parser program on your own. Do not look at the lecture, and the existing source code. The link contains the code where you need to start working on.
================================================
FILE: 23-input-scanning/questions/README.md
================================================
## What is an input stream?
1. Any data source that generates contiguous data like Standard Input *CORRECT*
2. An input from a user
3. The contents of a file
4. The contents of a website
> **1:** That's right. The input stream can come from any data source. Standard Input is one of them, and you can redirect it to almost any data source like user input, files, website contents and so on.
>
> **2-4:** Yes, that may be an input stream, but it doesn't explain what an input stream is.
>
## What does the program print?
```go
in := bufio.Scanner(os.Stdin)
in.Scan() // user enters: "hi!"
in.Scan() // user enters: "how are you?"
fmt.Println(in.Text())
```
1. "hi" and "how are you?"
2. "hi"
3. "how are you?" *CORRECT*
4. Nothing
> **3:** The Text() method only returns the last scanned token. A token can be a line or a word and so on.
>
## Using bufio.Scanner, how can you detect errors in the input stream?
1. Using the Err() method *CORRECT*
2. Using the Error() method
3. By checking whether the Scanner is nil or not
## How can you configure bufio.Scanner to only scan for the words?
```go
in := bufio.Scanner(os.Stdin)
// ...
```
1. `in = bufio.NewScanner(in, bufio.ScanWords)`
2. `in.Split(bufio.ScanWords)` *CORRECT*
3. `in.ScanWords()`
> **2:** That's right. bufio has a few splitters like ScanWords such as ScanLines (the default), ScanRunes, and so on.
>
## The function uses the "Must" prefix, why?
```go
regexp.MustCompile("...")
```
1. It's only being used for readability purposes
2. It's a guarantee that the function will work, no matter what
3. The function may crash your program *CORRECT*
> **3:** "Must" prefix is a convention. If a function or method may panic (= crash a program), then it's usually being prefixed with a "must" prefix.
>
================================================
FILE: 24-structs/01-intro/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
type Movie struct {
Title string
Genre string
Rating int
}
type Rental struct {
Address string
Rooms int
Size int
Price int
}
type Person struct {
Name string
Lastname string
Age int
}
person1 := Person{Name: "Pablo", Lastname: "Picasso", Age: 91}
person2 := Person{Name: "Sigmund", Lastname: "Freud", Age: 83}
fmt.Printf("person1: %+v\n", person1)
fmt.Printf("person2: %+v\n", person2)
type VideoGame struct {
Title string
Genre string
Published bool
}
pacman := VideoGame{
Title: "Pac-Man",
Genre: "Arcade Game",
Published: true,
}
fmt.Printf("pacman: %+v\n", pacman)
}
================================================
FILE: 24-structs/02-basics/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
/*
USING VARIABLES
*/
var (
name, lastname string
age int
name2, lastname2 string
age2 int
)
name, lastname, age = "Pablo", "Picasso", 95
name2, lastname2, age = "Sigmund", "Freud", 83
fmt.Println("Picasso:", name, lastname, age)
fmt.Println("Freud :", name2, lastname2, age2)
// var picasso struct {
// name, lastname string
// age int
// }
// var freud struct {
// name, lastname string
// age int
// }
// create a new struct type
type person struct {
name, lastname string
age int
}
// picasso := person{name: "Pablo", lastname: "Picasso", age: 91}
picasso := person{
name: "Pablo",
lastname: "Picasso",
age: 91,
}
var freud person
freud.name = "Sigmund"
freud.lastname = "Freud"
freud.age = 83
fmt.Printf("\n%s's age is %d\n", picasso.lastname, picasso.age)
fmt.Printf("\nPicasso: %#v\n", picasso)
fmt.Printf("Freud : %#v\n", freud)
}
================================================
FILE: 24-structs/03-compare-assign/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// #1b: create the song struct type
type song struct {
title, artist string
}
// #5: structs can contain other structs
type playlist struct {
genre string
// songTitles []string
// songArtist []string
// #6: include a slice of song structs
songs []song
}
func main() {
// #1: create two struct values with the same type
song1 := song{title: "wonderwall", artist: "oasis"}
song2 := song{title: "super sonic", artist: "oasis"}
fmt.Printf("song1: %+v\nsong2: %+v\n", song1, song2)
// #4: structs are copied
// song1 = song2
// #3: structs can be compared
if song1 == song2 {
// #2: struct comparison works like this
// if song1.title == song2.title &&
// song1.artist == song2.artist {
fmt.Println("songs are equal.")
} else {
fmt.Println("songs are not equal.")
}
// #8
songs := []song{
// #7b: you don't have to type the element types
{title: "wonderwall", artist: "oasis"},
{title: "supersonic", artist: "oasis"},
}
// #7: a struct can include another struct
rock := playlist{
genre: "indie rock",
songs: songs,
}
// #9: you can't compare struct values that contains incomparable fields
// you need to compare them manually
// clone := rock
// if rock.songs == clone {
// }
// if songs == songs {
// #11: song is a clone, it cannot change the original struct value
song := rock.songs[0]
song.title = "live forever"
// #11c: directly set the original one
rock.songs[0].title = "live forever"
// #11b
fmt.Printf("\n%+v\n%+v\n", song, rock.songs[0])
// #10: printing
fmt.Printf("\n%-20s %20s\n", "TITLE", "ARTIST")
for _, s := range rock.songs {
// s := rock.songs[i]
// #12b: s is a copy inside because struct values are copied
s.title = "destroy"
fmt.Printf("%-20s %20s\n", s.title, s.artist)
}
// #12
fmt.Printf("\n%-20s %20s\n", "TITLE", "ARTIST")
for _, s := range rock.songs {
fmt.Printf("%-20s %20s\n", s.title, s.artist)
}
}
================================================
FILE: 24-structs/04-embedding/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
// #1: declare the types
type text struct {
title string
words int
}
type book struct {
// title string
// words int
// #3: include the text as a field
// text text
// #4: embed the text
text
isbn string
// #5: add a conflicting field
title string
}
// #2: print a book
// moby := book{title: "moby dick", words: 206052, isbn: "102030"}
// fmt.Printf("%s has %d words (isbn: %s)\n", moby.title, moby.words, moby.isbn)
// #3b: type the text in its own field
moby := book{
// #5c: type the field in a new field
// title: "conflict",
text: text{title: "moby dick", words: 206052},
isbn: "102030",
}
moby.text.words = 1000
moby.words++
// // #4b: print the book
fmt.Printf("%s has %d words (isbn: %s)\n",
moby.title, // equals to: moby.text.title
moby.words, // equals to: moby.text.words
moby.isbn)
// #3c: print the book
// fmt.Printf("%s has %d words (isbn: %s)\n",
// moby.text.title, moby.text.words, moby.isbn)
// #5b: print the conflict
fmt.Printf("%#v\n", moby)
// go get -u github.com/davecgh/go-spew/spew
// spew.Dump(moby)
}
================================================
FILE: 24-structs/05-project-log-parser-structs/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 24-structs/05-project-log-parser-structs/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 24-structs/05-project-log-parser-structs/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 24-structs/05-project-log-parser-structs/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 24-structs/05-project-log-parser-structs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
// result stores the parsed result for a domain
type result struct {
domain string
visits int
// add more metrics if needed
}
// parser keep tracks of the parsing
type parser struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total int // total visits for all domains
lines int // number of parsed lines (for the error messages)
}
func main() {
p := parser{sum: make(map[string]result)}
// Scan the standard-in line by line
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
p.lines++
// Parse the fields
fields := strings.Fields(in.Text())
if len(fields) != 2 {
fmt.Printf("wrong input: %v (line #%d)\n", fields, p.lines)
return
}
domain := fields[0]
// Sum the total visits per domain
visits, err := strconv.Atoi(fields[1])
if visits < 0 || err != nil {
fmt.Printf("wrong input: %q (line #%d)\n", fields[1], p.lines)
return
}
// Collect the unique domains
if _, ok := p.sum[domain]; !ok {
p.domains = append(p.domains, domain)
}
// Keep track of total and per domain visits
p.total += visits
// You cannot assign to composite values
// p.sum[domain].visits += visits
// create and assign a new copy of `visit`
p.sum[domain] = result{
domain: domain,
visits: visits + p.sum[domain].visits,
}
}
// Print the visits per domain
sort.Strings(p.domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range p.domains {
parsed := p.sum[domain]
fmt.Printf("%-30s %10d\n", domain, parsed.visits)
}
// Print the total visits for all domains
fmt.Printf("\n%-30s %10d\n", "TOTAL", p.total)
// Let's handle the error
if err := in.Err(); err != nil {
fmt.Println("> Err:", err)
}
}
================================================
FILE: 24-structs/06-encoding/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"encoding/json"
"fmt"
)
type permissions map[string]bool // #3
type user struct { // #1
Name string `json:"username"`
Password string `json:"-"`
Permissions permissions `json:"perms,omitempty"` // #6
// name string // #1
// password string // #1
// permissions // #3
}
func main() {
users := []user{ // #2
{"inanc", "1234", nil},
{"god", "42", permissions{"admin": true}},
{"devil", "66", permissions{"write": true}},
}
// out, err := json.Marshal(users) // #4
out, err := json.MarshalIndent(users, "", "\t") // #5
if err != nil { // #4
fmt.Println(err)
return
}
fmt.Println(string(out)) // #4
}
================================================
FILE: 24-structs/07-decoding/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"encoding/json"
"fmt"
"os"
)
type user struct {
Name string `json:"username"`
Permissions map[string]bool `json:"perms"`
}
func main() {
var input []byte
for in := bufio.NewScanner(os.Stdin); in.Scan(); {
input = append(input, in.Bytes()...)
}
var users []user
if err := json.Unmarshal(input, &users); err != nil {
fmt.Println(err)
return
}
for _, user := range users {
fmt.Print("+ ", user.Name)
switch p := user.Permissions; {
case p == nil:
fmt.Print(" has no power.")
case p["admin"]:
fmt.Print(" is an admin.")
case p["write"]:
fmt.Print(" can write.")
}
fmt.Println()
}
}
================================================
FILE: 24-structs/07-decoding/users.json
================================================
[
{
"username": "inanc"
},
{
"username": "god",
"perms": {
"admin": true
}
},
{
"username": "devil",
"perms": {
"write": true
}
}
]
================================================
FILE: 24-structs/08-decoding-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
/* This lecture will be added later */
package main
import (
"bufio"
"encoding/json"
"fmt"
"os"
)
type user struct {
Name string `json:"username"`
Permissions map[string]bool `json:"perms"`
Devices []struct {
Name string `json:"name"`
Battery int `json:"battery"`
} `json:"devices"`
}
// type device struct {
// Name string `json:"name"`
// Battery int `json:"battery"`
// }
func main() {
var input []byte
for in := bufio.NewScanner(os.Stdin); in.Scan(); {
input = append(input, in.Bytes()...)
}
var users []user
if err := json.Unmarshal(input, &users); err != nil {
fmt.Println(err)
return
}
for _, user := range users {
fmt.Print("+ ", user.Name)
switch p := user.Permissions; {
case p == nil:
fmt.Print(" has no power.")
case p["admin"]:
fmt.Print(" is an admin.")
case p["write"]:
fmt.Print(" can write.")
}
for _, device := range user.Devices {
fmt.Printf("\n\t[ %-10s: %d%% ]", device.Name, device.Battery)
}
fmt.Println()
}
}
================================================
FILE: 24-structs/08-decoding-2/users.json
================================================
[
{
"username": "inanc",
"devices": [
{ "name": "laptop", "battery": 10 },
{ "name": "phone", "battery": 30 }
]
},
{
"username": "god",
"perms": {
"admin": true
},
"devices": [
{ "name": "omniverse", "battery": 95 }
]
},
{
"username": "devil",
"perms": {
"write": true
}
}
]
================================================
FILE: 24-structs/exercises/01-warmup/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Warm Up
//
// Starting with this exercise, you'll build a command-line
// game store.
//
// 1. Declare the following structs:
//
// + item: id (int), name (string), price (int)
//
// + game: embed the item, genre (string)
//
//
// 2. Create a game slice using the following data:
//
// id name price genre
//
// 1 god of war 50 action adventure
// 2 x-com 2 30 strategy
// 3 minecraft 20 sandbox
//
//
// 3. Print all the games.
//
// EXPECTED OUTPUT
// Please run the solution to see the output.
// ---------------------------------------------------------
func main() {
}
================================================
FILE: 24-structs/exercises/01-warmup/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
games := []game{
{
item: item{id: 1, name: "god of war", price: 50},
genre: "action adventure",
},
{item: item{id: 2, name: "x-com 2", price: 40}, genre: "strategy"},
{item: item{id: 3, name: "minecraft", price: 20}, genre: "sandbox"},
}
fmt.Printf("Inanc's game store has %d games.\n\n", len(games))
for _, g := range games {
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
}
================================================
FILE: 24-structs/exercises/02-list/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: List
//
// Now, it's time to add an interface to your program using
// the bufio.Scanner. So the users can list the games, or
// search for the games by id.
//
// 1. Scan for the input in a loop (use bufio.Scanner)
//
// 2. Print the available commands.
//
// 3. Implement the quit command: Quits from the loop.
//
// 4. Implement the list command: Lists all the games.
//
//
// EXPECTED OUTPUT
// Please run the solution and try the program with list and
// quit commands.
// ---------------------------------------------------------
func main() {
// use your solution from the previous exercise
}
================================================
FILE: 24-structs/exercises/02-list/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
games := []game{
{
item: item{id: 1, name: "god of war", price: 50},
genre: "action adventure",
},
{item: item{id: 2, name: "x-com 2", price: 40}, genre: "strategy"},
{item: item{id: 3, name: "minecraft", price: 20}, genre: "sandbox"},
}
fmt.Printf("Inanc's game store has %d games.\n", len(games))
in := bufio.NewScanner(os.Stdin)
for {
fmt.Printf(`
> list : lists all the games
> quit : quits
`)
if !in.Scan() {
break
}
fmt.Println()
switch in.Text() {
case "quit":
fmt.Println("bye!")
return
case "list":
for _, g := range games {
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
}
}
}
================================================
FILE: 24-structs/exercises/03-query-by-id/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Query By Id
//
// Add a new command: "id". So the users can query the games
// by id.
//
// 1. Before the loop, index the games by id (use a map).
//
// 2. Add the "id" command.
// When a user types: id 2
// It should print only the game with id: 2.
//
// 3. Handle the errors:
//
// id
// wrong id
//
// id HEY
// wrong id
//
// id 10
// sorry. I don't have the game
//
// id 1
// #1: "god of war" (action adventure) $50
//
// id 2
// #2: "x-com 2" (strategy) $40
//
//
// EXPECTED OUTPUT
// Please also run the solution and try the program with
// list, quit, and id commands to see it in action.
// ---------------------------------------------------------
func main() {
// use your solution from the previous exercise
}
================================================
FILE: 24-structs/exercises/03-query-by-id/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
games := []game{
{
item: item{id: 1, name: "god of war", price: 50},
genre: "action adventure",
},
{item: item{id: 2, name: "x-com 2", price: 40}, genre: "strategy"},
{item: item{id: 3, name: "minecraft", price: 20}, genre: "sandbox"},
}
// index the games by id
byID := make(map[int]game)
for _, g := range games {
byID[g.id] = g
}
fmt.Printf("Inanc's game store has %d games.\n", len(games))
in := bufio.NewScanner(os.Stdin)
for {
fmt.Printf(`
> list : lists all the games
> id N : queries a game by id
> quit : quits
`)
if !in.Scan() {
break
}
fmt.Println()
cmd := strings.Fields(in.Text())
if len(cmd) == 0 {
continue
}
switch cmd[0] {
case "quit":
fmt.Println("bye!")
return
case "list":
for _, g := range games {
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
case "id":
if len(cmd) != 2 {
fmt.Println("wrong id")
continue
}
id, err := strconv.Atoi(cmd[1])
if err != nil {
fmt.Println("wrong id")
continue
}
g, ok := byID[id]
if !ok {
fmt.Println("sorry. I don't have the game")
continue
}
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
}
}
================================================
FILE: 24-structs/exercises/04-encode/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Encode
//
// Add a new command: "save". Encode the games to json, and
// print it, then terminate the loop.
//
// 1. Create a new struct type with exported fields: ID, Name, Genre and Price.
//
// 2. Create a new slice using the new struct type.
//
// 3. Save the games into the new slice.
//
// 4. Encode the new slice.
//
//
// RESTRICTION
// Do not export the fields of the game struct.
//
//
// EXPECTED OUTPUT
// Inanc's game store has 3 games.
//
// > list : lists all the games
// > id N : queries a game by id
// > save : exports the data to json and quits
// > quit : quits
//
// save
//
// [
// {
// "id": 1,
// "name": "god of war",
// "genre": "action adventure",
// "price": 50
// },
// {
// "id": 2,
// "name": "x-com 2",
// "genre": "strategy",
// "price": 40
// },
// {
// "id": 3,
// "name": "minecraft",
// "genre": "sandbox",
// "price": 20
// }
// ]
//
// ---------------------------------------------------------
func main() {
// use your solution from the previous exercise
}
================================================
FILE: 24-structs/exercises/04-encode/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
games := []game{
{
item: item{id: 1, name: "god of war", price: 50},
genre: "action adventure",
},
{item: item{id: 2, name: "x-com 2", price: 40}, genre: "strategy"},
{item: item{id: 3, name: "minecraft", price: 20}, genre: "sandbox"},
}
// index the games by id
byID := make(map[int]game)
for _, g := range games {
byID[g.id] = g
}
fmt.Printf("Inanc's game store has %d games.\n", len(games))
in := bufio.NewScanner(os.Stdin)
for {
fmt.Printf(`
> list : lists all the games
> id N : queries a game by id
> save : exports the data to json and quits
> quit : quits
`)
if !in.Scan() {
break
}
fmt.Println()
cmd := strings.Fields(in.Text())
if len(cmd) == 0 {
continue
}
switch cmd[0] {
case "quit":
fmt.Println("bye!")
return
case "list":
for _, g := range games {
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
case "id":
if len(cmd) != 2 {
fmt.Println("wrong id")
continue
}
id, err := strconv.Atoi(cmd[1])
if err != nil {
fmt.Println("wrong id")
continue
}
g, ok := byID[id]
if !ok {
fmt.Println("sorry. I don't have the game")
continue
}
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
case "save":
type jsonGame struct {
ID int `json:"id"`
Name string `json:"name"`
Genre string `json:"genre"`
Price int `json:"price"`
}
// load the data into the encodable game values
var encodable []jsonGame
for _, g := range games {
encodable = append(encodable,
jsonGame{g.id, g.name, g.genre, g.price})
}
out, err := json.MarshalIndent(encodable, "", "\t")
if err != nil {
fmt.Println("Sorry:", err)
continue
}
fmt.Println(string(out))
return
}
}
}
================================================
FILE: 24-structs/exercises/05-decode/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: Decode
//
// At the beginning of the file:
//
// 1. Load the initial data to the game store from json.
// (see the data constant below)
//
// 2. Load the decoded values into the usual `game` values (to the games slice as well).
//
// So the rest of the program can work intact.
//
//
// HINT
//
// Move the jsonGame type to the top and reuse it both when
// loading the initial data, and in the "save" command.
//
//
// EXPECTED OUTPUT
// Please run the solution to see the output.
// ---------------------------------------------------------
const data = `
[
{
"id": 1,
"name": "god of war",
"genre": "action adventure",
"price": 50
},
{
"id": 2,
"name": "x-com 2",
"genre": "strategy",
"price": 40
},
{
"id": 3,
"name": "minecraft",
"genre": "sandbox",
"price": 20
}
]`
func main() {
// use your solution from the previous exercise
}
================================================
FILE: 24-structs/exercises/05-decode/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
)
const data = `
[
{
"id": 1,
"name": "god of war",
"genre": "action adventure",
"price": 50
},
{
"id": 2,
"name": "x-com 2",
"genre": "strategy",
"price": 40
},
{
"id": 3,
"name": "minecraft",
"genre": "sandbox",
"price": 20
}
]`
func main() {
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
// ----------------------------------------------------------
// DECODING SOLUTION:
// encodable and decodable game type
type jsonGame struct {
ID int `json:"id"`
Name string `json:"name"`
Genre string `json:"genre"`
Price int `json:"price"`
}
// load the initial data from json
var decoded []jsonGame
if err := json.Unmarshal([]byte(data), &decoded); err != nil {
fmt.Println("Sorry, there is a problem:", err)
return
}
// load the data into usual game values
var games []game
for _, dg := range decoded {
games = append(games, game{item{dg.ID, dg.Name, dg.Price}, dg.Genre})
}
// ----------------------------------------------------------
// index the games by id
byID := make(map[int]game)
for _, g := range games {
byID[g.id] = g
}
fmt.Printf("Inanc's game store has %d games.\n", len(games))
in := bufio.NewScanner(os.Stdin)
for {
fmt.Printf(`
> list : lists all the games
> id N : queries a game by id
> save : exports the data to json and quits
> quit : quits
`)
if !in.Scan() {
break
}
fmt.Println()
cmd := strings.Fields(in.Text())
if len(cmd) == 0 {
continue
}
switch cmd[0] {
case "quit":
fmt.Println("bye!")
return
case "list":
for _, g := range games {
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
case "id":
if len(cmd) != 2 {
fmt.Println("wrong id")
continue
}
id, err := strconv.Atoi(cmd[1])
if err != nil {
fmt.Println("wrong id")
continue
}
g, ok := byID[id]
if !ok {
fmt.Println("sorry. I don't have the game")
continue
}
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
case "save":
// load the data into the encodable game values
var encodable []jsonGame
for _, g := range games {
encodable = append(encodable,
jsonGame{g.id, g.name, g.genre, g.price})
}
out, err := json.MarshalIndent(encodable, "", "\t")
if err != nil {
fmt.Println("Sorry:", err)
continue
}
fmt.Println(string(out))
return
}
}
}
================================================
FILE: 24-structs/exercises/README.md
================================================
# Struct Exercises
You'll build a queryable command-line game store.
1. **[Warm Up](https://github.com/inancgumus/learngo/tree/master/24-structs/exercises/01-warmup)**
Load up the data into the game store.
2. **[List](https://github.com/inancgumus/learngo/tree/master/24-structs/exercises/02-list)**
Now, it's time to add an interface to your program using the bufio.Scanner. So the users can list the games, or search for the games by id.
3. **[Query By Id](https://github.com/inancgumus/learngo/tree/master/24-structs/exercises/03-query-by-id)**
Add a new command: "id". So the users can query the games by id.
4. **[Encode](https://github.com/inancgumus/learngo/tree/master/24-structs/exercises/04-encode)**
Add a new command: "save". Encode the games to json, and print it, then terminate the loop.
5. **[Decode](https://github.com/inancgumus/learngo/tree/master/24-structs/exercises/05-decode)**
Load the initial data to the game store from json.
================================================
FILE: 24-structs/questions/README.md
================================================
## When should you use a struct type?
1. For storing the same type of values
2. For adding an additional type of values in runtime
3. For combining different types in a single type to represent a concept *CORRECT*
> **1:** Arrays, slices, and maps are better candidates for that.
>
> **2:** Struct fields are fixed at compile-time, you cannot add additional fields in runtime, neither you can remove them.
>
> **3:** That's right. A struct type combines different types of fields in a single type. You can use a struct type to represent a concept.
>
## What are the properties of struct fields?
1. They all should be of the same type
2. Each one should have a name and possibly a different type *CORRECT*
3. You can add additional fields in runtime
4. You can remove the existing fields in runtime
> **2:** Yes, each field should have a unique name. Also, each field should have a type, but every field can have a different type.
>
## What is wrong with the following code?
```go
type weather struct {
temperature, humidity float64
windSpeed float64
temperature float64
}
```
1. Nothing is wrong with it
2. `temperature, humidity float64` field is a syntax error
3. `temperature` field is not unique *CORRECT*
> **2:** That's a parallel definition. It defines two float64 fields: temperature and humidity. It is correct.
>
> **3:** Right! Struct field names should be unique.
>
## What is the zero-value of the following struct value?
```go
var movie struct {
title, genre string
rating float64
released bool
}
```
1. `{}`
2. `{title: "", genre: "", rating: 0, released: false}` *CORRECT*
3. `{title: "", genre: "", rating: 0, released: true}`
4. `{"title, genre": "", rating: 0, released: false}`
> **1:** That's an empty struct value with no fields.
>
> **2:** Right! Go initializes a struct's fields to zero-values depending on their type.
>
## What is the type of the following struct?
```go
avengers := struct {
title, genre string
rating float64
released bool
}{
"avengers: end game", "sci-fi", 8.9, true,
}
fmt.Printf("%T\n", avengers)
```
1. `struct{}`
2. `struct{ string; string; float64; bool }`
3. `struct{ title string; genre string; rating float64; released bool }` *CORRECT*
4. `{title: "avengers: end game"; genre: "sci-fi"; rating: 8.9; released: true}`
> **1:** That's an empty struct type with no fields.
>
> **2:** Fields names is also a part of a struct's type.
>
> **3:** Right! Field names and types are part of a struct's type.
>
> **4:** Nope, that's a struct value.
>
## Are the following struct values equal?
```go
type movie struct {
title, genre string
rating float64
released bool
}
avengers := movie{"avengers: end game", "sci-fi", 8.9, true}
clone := movie{
title: "avengers: end game", genre: "sci-fi",
rating: 8.9, released: true,
}
```
1. There is a syntax error
2. Yes *CORRECT*
3. No
> **2:** When creating a struct value, it doesn't matter whether you use the field names or not. So, they are equal.
>
## Are the following struct values equal? If not, why?
```go
type movie struct {
title, genre string
rating float64
released bool
}
avengers := movie{
title: "avengers: end game", genre: "sci-fi",
rating: 8.9, released: true,
}
clone := movie{title: "avengers: end game", genre: "sci-fi"}
fmt.Println(avengers == clone)
```
1. Yes: They have the same set of fields
2. No : They are not comparable
3. No : Field values are different *CORRECT*
> **1:** That's right, this means they are comparable, but that's not enough.
>
> **2:** Yes, they are. They use the same struct type.
>
> **3:** Yes, when you omit some of the fields, Go assigns zero values to them. Here, "clone" struct value's "rating" and "released" fields are: 0, and false, respectively.
>
## Do the movie and performance struct types have the same types?
```go
type item struct { title string }
type movie struct { item }
type performance struct { item }
```
1. Yes: They have the same set of fields
2. No : They have different type names *CORRECT*
3. No : An embedded field cannot be compared
> **2:** Right! Types with different names cannot be compared. However, you can convert one of them to the other because they have the same set of fields. movie{} == movie(performance{}) is ok, or vice versa.
>
## What does the program print?
```go
type item struct{ title string }
type movie struct {
item
title string
}
m := movie{
title: "avengers: end game",
item: item{"midnight in paris"},
}
fmt.Println(m.title, "&", m.item.title)
```
1. midnight in paris & midnight in paris
2. avengers: end game & avengers: end game
3. midnight in paris & avengers: end game
4. avengers: end game & midnight in paris *CORRECT*
> **4:** Right! `m.title` returns "avengers: end game" because the outer type always takes priority. However, `m.item.title` returns "midnight in paris" because you explicitly get it from the inner type: item.
>
## What is a field tag?
1. It allows Go to index struct fields more efficiently
2. You can use it for documenting your code
3. It's like a comment
4. Associates metadata about the field *CORRECT*
> **4:** Correct. For example, the json package can read and encode/decode depending on the associated metadata.
## Which one is correct about a field tag?
1. It needs to be typed according to some rules
2. You can change it to a different value in runtime
3. It's just a string value, and it doesn't have a meaning on its own *CORRECT*
> **1:** This is true to some extent but it can have any value.
>
> **2:** Fields tags are part of a struct type definition so you cannot change their value in runtime.
>
> **3:** Right! It's just a string value. It's only meaningful when other code reads it. For example, the json package can read it and encode/decode depending on the field tag's value.
>
## What is wrong with the following program?
```go
type movie struct {
title string `json:"title"`
}
m := movie{"black panthers"}
encoded, _ := json.Marshal(m)
fmt.Println(string(encoded))
```
1. `movie` is unexported so you cannot encode
2. `title` is unexported so you cannot encode *CORRECT*
3. Error handling is missing so you cannot encode
> **1:** The json package can encode a struct even though its type is unexported.
>
> **2:** Right! The json package can only encode exported fields.
>
> **3:** It's better to handle errors but it's not the main problem here.
>
## Why do you need to pass a pointer to the Unmarshal function?
1. To make it work faster and efficient
2. So it can update the value on memory *CORRECT*
3. To prevent errors
> **2:** Otherwise, it would not be able to update the given value. It's because, every value in Go is passed by value. So a function can only change the copy, not the original value. However, through a pointer, a function can change the original value.
================================================
FILE: 25-functions/01-basics/bad.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func showN() {
if N == 0 {
return
}
fmt.Printf("showN : N is %d\n", N)
}
func incrN() {
N++
}
// you cannot declare a function within the same package with the same name
// func incrN() {
// }
================================================
FILE: 25-functions/01-basics/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
//
// You need run this program like so:
// go run .
//
// This will magically pass all the go files in the current directory to the
// Go compiler.
//
//
// BUT NOT like so:
// go run main.go
//
// Because, the compiler needs to see bad.go too
// It can't magically find bad.go — what you give is what you get.
//
package main
// N is a shared counter which is BAD
var N int
func main() {
showN()
incrN()
incrN()
showN()
}
================================================
FILE: 25-functions/02-basics/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
)
func main() {
local := 10
show(local)
incrWrong(local)
fmt.Printf("local → %d\n", local)
// incr(local)
local = incr(local)
show(local)
local = incrBy(local, 5)
show(local)
_, err := incrByStr(local, "TWO")
if err != nil {
fmt.Printf("err → %s\n", err)
}
local, _ = incrByStr(local, "2")
show(local)
// CHAINING
// can't save the number back into main's local
show(incrBy(local, 2))
show(local)
// can't pass the results of the multiple-value returning func
// show(incrByStr(local, "3"))
// can call showErr directly because it accepts the same types
// of parameters as with incrByStr's result values.
// local = sanitize(incrByStr(local, "NOPE"))
// show(local)
local = sanitize(incrByStr(local, "2"))
show(local)
local = limit(incrBy(local, 5), 2000)
show(local)
}
func show(n int) {
// can't access main's local
// fmt.Printf("show : n = %d\n", local)
fmt.Printf("show → n = %d\n", n)
}
// wrong: incr can't access to main's `local`
func incrWrong(n int) {
// n := local
n++
// can't return (there are no result values)
// return n
}
func incr(n int) int {
n++
return n
}
func incrBy(n, factor int) int {
return n * factor
}
func incrByStr(n int, factor string) (int, error) {
m, err := strconv.Atoi(factor)
n = incrBy(n, m)
return n, err
}
func sanitize(n int, err error) int {
if err != nil {
return 0
}
return n
}
func limit(n, lim int) (m int) {
// var m int
m = n
if m >= lim {
m = lim
}
// return m
return
}
================================================
FILE: 25-functions/03-refactor-to-funcs/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/03-refactor-to-funcs/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/03-refactor-to-funcs/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/03-refactor-to-funcs/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/03-refactor-to-funcs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
func main() {
p := newParser()
// Scan the standard-in line by line
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
p.lines++
parsed, err := parse(p, in.Text())
if err != nil {
fmt.Println(err)
return
}
domain, visits := parsed.domain, parsed.visits
// Collect the unique domains
if _, ok := p.sum[domain]; !ok {
p.domains = append(p.domains, domain)
}
// Keep track of total and per domain visits
p.total += visits
// create and assign a new copy of `visit`
p.sum[domain] = result{
domain: domain,
visits: visits + p.sum[domain].visits,
}
}
// Print the visits per domain
sort.Strings(p.domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range p.domains {
parsed := p.sum[domain]
fmt.Printf("%-30s %10d\n", domain, parsed.visits)
}
// Print the total visits for all domains
fmt.Printf("\n%-30s %10d\n", "TOTAL", p.total)
// Let's handle the error
if err := in.Err(); err != nil {
fmt.Println("> Err:", err)
}
}
================================================
FILE: 25-functions/03-refactor-to-funcs/parser.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
// result stores the parsed result for a domain
type result struct {
domain string
visits int
// add more metrics if needed
}
// parser keep tracks of the parsing
type parser struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total int // total visits for all domains
lines int // number of parsed lines (for the error messages)
}
// newParser constructs, initializes and returns a new parser
func newParser() parser {
return parser{sum: make(map[string]result)}
}
// parse parses a log line and returns the parsed result with an error
func parse(p parser, line string) (parsed result, err error) {
fields := strings.Fields(line)
if len(fields) != 2 {
err = fmt.Errorf("wrong input: %v (line #%d)", fields, p.lines)
return
}
parsed.domain = fields[0]
parsed.visits, err = strconv.Atoi(fields[1])
if parsed.visits < 0 || err != nil {
err = fmt.Errorf("wrong input: %q (line #%d)", fields[1], p.lines)
return
}
return
}
================================================
FILE: 25-functions/04-pass-by-value-semantics/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/04-pass-by-value-semantics/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/04-pass-by-value-semantics/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/04-pass-by-value-semantics/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/04-pass-by-value-semantics/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
func main() {
p := newParser()
// Scan the standard-in line by line
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
p.lines++
parsed, err := parse(p, in.Text())
if err != nil {
fmt.Println(err)
return
}
p = update(p, parsed)
}
// Print the visits per domain
sort.Strings(p.domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range p.domains {
parsed := p.sum[domain]
fmt.Printf("%-30s %10d\n", domain, parsed.visits)
}
// Print the total visits for all domains
fmt.Printf("\n%-30s %10d\n", "TOTAL", p.total)
// Let's handle the error
if err := in.Err(); err != nil {
fmt.Println("> Err:", err)
}
}
================================================
FILE: 25-functions/04-pass-by-value-semantics/parser.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
// result stores the parsed result for a domain
type result struct {
domain string
visits int
// add more metrics if needed
}
// parser keep tracks of the parsing
type parser struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total int // total visits for all domains
lines int // number of parsed lines (for the error messages)
}
// newParser constructs, initializes and returns a new parser
func newParser() parser {
return parser{sum: make(map[string]result)}
}
// parse parses a log line and returns the parsed result with an error
func parse(p parser, line string) (parsed result, err error) {
fields := strings.Fields(line)
if len(fields) != 2 {
err = fmt.Errorf("wrong input: %v (line #%d)", fields, p.lines)
return
}
parsed.domain = fields[0]
parsed.visits, err = strconv.Atoi(fields[1])
if parsed.visits < 0 || err != nil {
err = fmt.Errorf("wrong input: %q (line #%d)", fields[1], p.lines)
return
}
return
}
// update updates the parser for the given parsing result
func update(p parser, parsed result) parser {
domain, visits := parsed.domain, parsed.visits
// Collect the unique domains
if _, ok := p.sum[domain]; !ok {
p.domains = append(p.domains, domain)
}
// Keep track of total and per domain visits
p.total += visits
// create and assign a new copy of `visit`
p.sum[domain] = result{
domain: domain,
visits: visits + p.sum[domain].visits,
}
return p
}
================================================
FILE: 25-functions/exercises/README.md
================================================
# Function Exercises
1. **[Refactor the Game Store to Funcs - Step #1](https://github.com/inancgumus/learngo/tree/master/25-functions/exercises/refactor-to-funcs-1)**
Remember the game store program from the structs exercises? Now, it's time to refactor it to funcs.
2. **[Refactor the Game Store to Funcs - Step #2](https://github.com/inancgumus/learngo/tree/master/25-functions/exercises/refactor-to-funcs-2)**
Let's continue the refactoring from the previous exercise. This time, you're going to refactor the command handling logic.
3. **[Refactor the Game Store to Funcs - Step #3](https://github.com/inancgumus/learngo/tree/master/25-functions/exercises/refactor-to-funcs-3)**
Let's continue from the previous exercise. This time, you're going to add json encoding and decoding using funcs.
4. **[Rewrite the Log Parser program using funcs](https://github.com/inancgumus/learngo/tree/master/25-functions/exercises/rewrite-log-parser-using-funcs)**
You've watched the lecture. Now, try to rewrite the same log parser program using funcs on your own.
================================================
FILE: 25-functions/exercises/refactor-to-funcs-1/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Refactor the game store to funcs - step #1
//
// Remember the game store program from the structs exercises?
// Now, it's time to refactor it to funcs.
//
// Create games.go file
//
// 1- Move the structs there
//
// 2- Add a func that creates and returns a game.
//
// Name : newGame
// Inputs: id, price, name and genre
// Output: game
//
// 3- Add a func that adds a `game` to `[]game` and returns `[]game`:
//
// Name : addGame
// Inputs: []game, game
// Output: []game
//
// 4- Add a func that uses newGame and addGame funcs to load up the game
// store:
//
// Name : load
// Inputs: none
// Output: []game
//
// 5- Add a func that indexes games by ID:
//
// Name : indexByID
// Inputs: []game
// Output: map[int]game
//
// 6- Add a func that prints the given game:
//
// Name : printGame
// Inputs: game
//
//
// Go back to main.go and change the existing code with
// the new funcs that you've created. There are hints
// inside the code.
//
// ---------------------------------------------------------
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
// load()
games := []game{
{
item: item{id: 1, name: "god of war", price: 50},
genre: "action adventure",
},
{item: item{id: 2, name: "x-com 2", price: 40}, genre: "strategy"},
{item: item{id: 3, name: "minecraft", price: 20}, genre: "sandbox"},
}
// indexByID()
byID := make(map[int]game)
for _, g := range games {
byID[g.id] = g
}
fmt.Printf("Inanc's game store has %d games.\n", len(games))
in := bufio.NewScanner(os.Stdin)
for {
fmt.Printf(`
> list : lists all the games
> id N : queries a game by id
> quit : quits
`)
if !in.Scan() {
break
}
fmt.Println()
cmd := strings.Fields(in.Text())
if len(cmd) == 0 {
continue
}
switch cmd[0] {
case "quit":
fmt.Println("bye!")
return
case "list":
for _, g := range games {
// printGame()
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
case "id":
if len(cmd) != 2 {
fmt.Println("wrong id")
continue
}
id, err := strconv.Atoi(cmd[1])
if err != nil {
fmt.Println("wrong id")
continue
}
g, ok := byID[id]
if !ok {
fmt.Println("sorry. I don't have the game")
continue
}
// printGame()
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
}
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-1/solution/games.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
func load() (games []game) {
games = addGame(games, newGame(1, 50, "god of war", "action adventure"))
games = addGame(games, newGame(2, 40, "x-com 2", "strategy"))
games = addGame(games, newGame(3, 20, "minecraft", "sandbox"))
return
}
func addGame(games []game, g game) []game {
return append(games, g)
}
func newGame(id, price int, name, genre string) game {
return game{
item: item{id: id, name: name, price: price},
genre: genre,
}
}
func indexByID(games []game) (byID map[int]game) {
byID = make(map[int]game)
for _, g := range games {
byID[g.id] = g
}
return
}
func printGame(g game) {
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-1/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
games := load()
byID := indexByID(games)
fmt.Printf("Inanc's game store has %d games.\n", len(games))
in := bufio.NewScanner(os.Stdin)
for {
fmt.Printf(`
> list : lists all the games
> id N : queries a game by id
> quit : quits
`)
if !in.Scan() {
break
}
fmt.Println()
cmd := strings.Fields(in.Text())
if len(cmd) == 0 {
continue
}
switch cmd[0] {
case "quit":
fmt.Println("bye!")
return
case "list":
for _, g := range games {
printGame(g)
}
case "id":
if len(cmd) != 2 {
fmt.Println("wrong id")
continue
}
id, err := strconv.Atoi(cmd[1])
if err != nil {
fmt.Println("wrong id")
continue
}
g, ok := byID[id]
if !ok {
fmt.Println("sorry. I don't have the game")
continue
}
printGame(g)
}
}
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-2/games.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
func load() (games []game) {
games = addGame(games, newGame(1, 50, "god of war", "action adventure"))
games = addGame(games, newGame(2, 40, "x-com 2", "strategy"))
games = addGame(games, newGame(3, 20, "minecraft", "sandbox"))
return
}
func addGame(games []game, g game) []game {
return append(games, g)
}
func newGame(id, price int, name, genre string) game {
return game{
item: item{id: id, name: name, price: price},
genre: genre,
}
}
func indexByID(games []game) (byID map[int]game) {
byID = make(map[int]game)
for _, g := range games {
byID[g.id] = g
}
return
}
func printGame(g game) {
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Refactor the game store to funcs - step #2
//
// Let's continue the refactoring from the previous
// exercise. This time, you're going to refactor the
// command handling logic.
//
//
// Create commands.go file
//
// 1- Add a func that runs the given command from the user:
//
// Name : runCmd
// Inputs: input string, []game, map[int]game
// Output: bool
//
// This func returns true if it wants the program to
// continue. When it returns false, the program will
// terminate. So, all the commands that it calls need
// to return true or false as well depending on whether
// they want to cause the program to terminate or not.
//
// 2- Add a func that handles the quit command:
//
// Name : cmdQuit
// Input : none
// Output: bool
//
// 3- Add a func that handles the list command:
//
// Name : cmdList
// Inputs: []game
// Output: bool
//
// 4- Add a func that handles the id command:
//
// Name : cmdByID
// Inputs: cmd []string, []game, map[int]game
// Output: bool
//
// 5- Refactor the runCmd() with the cmdXXX funcs.
//
// Go back to main.go and change the existing code with
// the new funcs that you've created. There are hints
// inside the code.
//
// ---------------------------------------------------------
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
games := load()
byID := indexByID(games)
fmt.Printf("Inanc's game store has %d games.\n", len(games))
in := bufio.NewScanner(os.Stdin)
for {
// menu()
fmt.Printf(`
> list : lists all the games
> id N : queries a game by id
> quit : quits
`)
if !in.Scan() {
break
}
// --- runCmd start ---
fmt.Println()
cmd := strings.Fields(in.Text())
if len(cmd) == 0 {
continue
}
switch cmd[0] {
case "quit":
// cmdQuit()
fmt.Println("bye!")
return
case "list":
// cmdList()
for _, g := range games {
printGame(g)
}
case "id":
// cmdByID
if len(cmd) != 2 {
fmt.Println("wrong id")
continue
}
id, err := strconv.Atoi(cmd[1])
if err != nil {
fmt.Println("wrong id")
continue
}
g, ok := byID[id]
if !ok {
fmt.Println("sorry. I don't have the game")
continue
}
printGame(g)
}
// --- runCmd end ---
}
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-2/solution/commands.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
func runCmd(input string, games []game, byID map[int]game) bool {
fmt.Println()
cmd := strings.Fields(input)
if len(cmd) == 0 {
return true
}
switch cmd[0] {
case "quit":
return cmdQuit()
case "list":
return cmdList(games)
case "id":
return cmdByID(cmd, games, byID)
}
return true
}
func cmdQuit() bool {
fmt.Println("bye!")
return false
}
func cmdList(games []game) bool {
for _, g := range games {
printGame(g)
}
return true
}
func cmdByID(cmd []string, games []game, byID map[int]game) bool {
if len(cmd) != 2 {
fmt.Println("wrong id")
return true
}
id, err := strconv.Atoi(cmd[1])
if err != nil {
fmt.Println("wrong id")
return true
}
g, ok := byID[id]
if !ok {
fmt.Println("sorry. I don't have the game")
return true
}
printGame(g)
return true
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-2/solution/games.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
func load() (games []game) {
games = addGame(games, newGame(1, 50, "god of war", "action adventure"))
games = addGame(games, newGame(2, 40, "x-com 2", "strategy"))
games = addGame(games, newGame(3, 20, "minecraft", "sandbox"))
return
}
func addGame(games []game, g game) []game {
return append(games, g)
}
func newGame(id, price int, name, genre string) game {
return game{
item: item{id: id, name: name, price: price},
genre: genre,
}
}
func indexByID(games []game) (byID map[int]game) {
byID = make(map[int]game)
for _, g := range games {
byID[g.id] = g
}
return
}
func printGame(g game) {
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
games := load()
byID := indexByID(games)
fmt.Printf("Inanc's game store has %d games.\n", len(games))
in := bufio.NewScanner(os.Stdin)
for {
fmt.Printf(`
> list : lists all the games
> id N : queries a game by id
> quit : quits
`)
if !in.Scan() || !runCmd(in.Text(), games, byID) {
break
}
}
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-3/commands.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
func runCmd(input string, games []game, byID map[int]game) bool {
fmt.Println()
cmd := strings.Fields(input)
if len(cmd) == 0 {
return true
}
switch cmd[0] {
case "quit":
return cmdQuit()
case "list":
return cmdList(games)
case "id":
return cmdByID(cmd, games, byID)
}
return true
}
func cmdQuit() bool {
fmt.Println("bye!")
return false
}
func cmdList(games []game) bool {
for _, g := range games {
printGame(g)
}
return true
}
func cmdByID(cmd []string, games []game, byID map[int]game) bool {
if len(cmd) != 2 {
fmt.Println("wrong id")
return true
}
id, err := strconv.Atoi(cmd[1])
if err != nil {
fmt.Println("wrong id")
return true
}
g, ok := byID[id]
if !ok {
fmt.Println("sorry. I don't have the game")
return true
}
printGame(g)
return true
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-3/games.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
const data = `
[
{
"id": 1,
"name": "god of war",
"genre": "action adventure",
"price": 50
},
{
"id": 2,
"name": "x-com 2",
"genre": "strategy",
"price": 40
},
{
"id": 3,
"name": "minecraft",
"genre": "sandbox",
"price": 20
}
]`
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
func load() (games []game) {
games = addGame(games, newGame(1, 50, "god of war", "action adventure"))
games = addGame(games, newGame(2, 40, "x-com 2", "strategy"))
games = addGame(games, newGame(3, 20, "minecraft", "sandbox"))
return
}
func addGame(games []game, g game) []game {
return append(games, g)
}
func newGame(id, price int, name, genre string) game {
return game{
item: item{id: id, name: name, price: price},
genre: genre,
}
}
func indexByID(games []game) (byID map[int]game) {
byID = make(map[int]game)
for _, g := range games {
byID[g.id] = g
}
return
}
func printGame(g game) {
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-3/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Refactor the game store to funcs - step #3
//
// Let's continue from the previous exercise. This time,
// you're going to add json encoding and decoding using
// funcs.
//
// 1- Create a new command in a func that encodes the
// game store data to json and terminates the program.
// Lastly, add it to runCmd func.
//
// For more information, see: "Encode" exercise from
// the structs section.
//
// Name : cmdSave
// Inputs: []game
// Output: bool
//
// 2- Refactor the load() to load the games from the
// `data` constant (it's in the games.go as well).
//
// For more information, see: "Decode" exercise from
// the structs section.
//
// ---------------------------------------------------------
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
games := load()
byID := indexByID(games)
fmt.Printf("Inanc's game store has %d games.\n", len(games))
in := bufio.NewScanner(os.Stdin)
for {
fmt.Printf(`
> list : lists all the games
> id N : queries a game by id
> quit : quits
`)
if !in.Scan() || !runCmd(in.Text(), games, byID) {
break
}
}
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-3/solution/commands.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"encoding/json"
"fmt"
"strconv"
"strings"
)
func runCmd(input string, games []game, byID map[int]game) bool {
fmt.Println()
cmd := strings.Fields(input)
if len(cmd) == 0 {
return true
}
switch cmd[0] {
case "quit":
return cmdQuit()
case "list":
return cmdList(games)
case "id":
return cmdByID(cmd, games, byID)
case "save":
return cmdSave(games)
}
return true
}
func cmdQuit() bool {
fmt.Println("bye!")
return false
}
func cmdList(games []game) bool {
for _, g := range games {
printGame(g)
}
return true
}
func cmdByID(cmd []string, games []game, byID map[int]game) bool {
if len(cmd) != 2 {
fmt.Println("wrong id")
return true
}
id, err := strconv.Atoi(cmd[1])
if err != nil {
fmt.Println("wrong id")
return true
}
g, ok := byID[id]
if !ok {
fmt.Println("sorry. I don't have the game")
return true
}
printGame(g)
return true
}
func cmdSave(games []game) bool {
// load the data into encodable game values
var jg []jsonGame
for _, g := range games {
jg = append(jg, jsonGame{g.id, g.name, g.genre, g.price})
}
out, err := json.MarshalIndent(jg, "", "\t")
if err != nil {
fmt.Println("sorry, can't save:", err)
return true
}
fmt.Println(string(out))
return false
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-3/solution/games.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"encoding/json"
"fmt"
)
const data = `
[
{
"id": 1,
"name": "god of war",
"genre": "action adventure",
"price": 50
},
{
"id": 2,
"name": "x-com 2",
"genre": "strategy",
"price": 40
},
{
"id": 3,
"name": "minecraft",
"genre": "sandbox",
"price": 20
}
]`
type item struct {
id int
name string
price int
}
type game struct {
item
genre string
}
// encodable and decodable game type
type jsonGame struct {
ID int `json:"id"`
Name string `json:"name"`
Genre string `json:"genre"`
Price int `json:"price"`
}
func load() (games []game) {
// load the initial data from json
var decoded []jsonGame
if err := json.Unmarshal([]byte(data), &decoded); err != nil {
fmt.Println("Sorry, there is a problem:", err)
return
}
// load the data into usual game values
for _, dg := range decoded {
games = addGame(games, newGame(dg.ID, dg.Price, dg.Name, dg.Genre))
}
return games
}
func addGame(games []game, g game) []game {
return append(games, g)
}
func newGame(id, price int, name, genre string) game {
return game{
item: item{id: id, name: name, price: price},
genre: genre,
}
}
func indexByID(games []game) (byID map[int]game) {
byID = make(map[int]game)
for _, g := range games {
byID[g.id] = g
}
return
}
func printGame(g game) {
fmt.Printf("#%d: %-15q %-20s $%d\n",
g.id, g.name, "("+g.genre+")", g.price)
}
================================================
FILE: 25-functions/exercises/refactor-to-funcs-3/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
games := load()
byID := indexByID(games)
fmt.Printf("Inanc's game store has %d games.\n", len(games))
in := bufio.NewScanner(os.Stdin)
for {
fmt.Printf(`
> list : lists all the games
> id N : queries a game by id
> save : exports the data to json and quits
> quit : quits
`)
if !in.Scan() || !runCmd(in.Text(), games, byID) {
break
}
}
}
================================================
FILE: 25-functions/exercises/rewrite-log-parser-using-funcs/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/exercises/rewrite-log-parser-using-funcs/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/exercises/rewrite-log-parser-using-funcs/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/exercises/rewrite-log-parser-using-funcs/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 25-functions/exercises/rewrite-log-parser-using-funcs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
// result stores the parsed result for a domain
type result struct {
domain string
visits int
// add more metrics if needed
}
// parser keep tracks of the parsing
type parser struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total int // total visits for all domains
lines int // number of parsed lines (for the error messages)
}
func main() {
p := parser{sum: make(map[string]result)}
// Scan the standard-in line by line
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
p.lines++
// Parse the fields
fields := strings.Fields(in.Text())
if len(fields) != 2 {
fmt.Printf("wrong input: %v (line #%d)\n", fields, p.lines)
return
}
domain := fields[0]
// Sum the total visits per domain
visits, err := strconv.Atoi(fields[1])
if visits < 0 || err != nil {
fmt.Printf("wrong input: %q (line #%d)\n", fields[1], p.lines)
return
}
// Collect the unique domains
if _, ok := p.sum[domain]; !ok {
p.domains = append(p.domains, domain)
}
// Keep track of total and per domain visits
p.total += visits
// You cannot assign to composite values
// p.sum[domain].visits += visits
// create and assign a new copy of `visit`
p.sum[domain] = result{
domain: domain,
visits: visits + p.sum[domain].visits,
}
}
// Print the visits per domain
sort.Strings(p.domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range p.domains {
parsed := p.sum[domain]
fmt.Printf("%-30s %10d\n", domain, parsed.visits)
}
// Print the total visits for all domains
fmt.Printf("\n%-30s %10d\n", "TOTAL", p.total)
// Let's handle the error
if err := in.Err(); err != nil {
fmt.Println("> Err:", err)
}
}
================================================
FILE: 25-functions/questions/README.md
================================================
## Which one is a correct function declaration?
1. add func(a, b int) {}
2. function run(a int, b int) {}
3. func run(int a, b) {}
4. func run(a, b int) {} *CORRECT*
## Which one is the input and result names of the following func?
```go
func run(p Process, id1, id2 int) (pid int, err error) {}
```
1. Inputs: p, id1, and id2. Results: pid, err. *CORRECT*
2. Inputs: Process, int, int. Results: int, error.
3. Inputs: run, p, id1, id2. Results: pid, err.
4. The declaration syntax is wrong.
## What is a return statement?
1. Terminates a program.
2. Terminates a func by returning zero or more values to a caller func. *CORRECT*
3. Skips the next statement and runs the next.
## What is wrong with the following code?
```go
func add(a, b int) {
return a + b
return
}
```
1. The return statement should be called only once
2. The last return statement is wrong
3. It should declare an int result value and remove the last return statement *CORRECT*
4. It should declare any numeric result value
> **2:** Actually, it is correct because the func doesn't declare a result value.
>
> **3:** Correct. It should be: `func add(a, b int) int { return a + b }`
## How to fix the following code?
```go
func incr(a int) {
a++
return
}
num := 10
// You want it to print 11 but it prints 10 instead.
fmt.Println( incr(num) )
```
1. Change the func: `func incr(a int) int { a++; return a }` *CORRECT*
2. Change the func: `func incr(a int, newA int) { a++; newA = a }`
3. Change the func: `func incr(a int) int { return a++ }`
> **1:** Go is a 100% pass-by-value language. So, the inputs to a func are local to that function: The changes are not visible outside of that func.
## Why should you not use package level variables?
1. Nothing is wrong with them
2. Funcs cannot use package level variables
3. They may increase code coupling and cause fragile code *CORRECT*
> **3:** It's because: Anyone can access and change them.
## Why should you return an error from the following func?
```go
// Why this?
func incr(n string) (int, error) {
m, err := strconv.Atoi(n)
return n + 1, err
}
// Instead of this?
func incr(n string) int {
m, _ := strconv.Atoi(n)
return m + 1
}
```
1. You want to let the caller know when something goes wrong *CORRECT*
2. When an error occurs, `Atoi` returns 0, so you don't need to return an error
> **2:** Sometimes, this is partly true however it is better to let the caller know when something goes wrong.
## How and why does the following return statement work?
```go
func spread(samples int, P int) (estimated float64) {
for i := 0; i < P; i++ {
estimated += estimate(i, P)
}
return
}
```
1. `estimated` is a named result value. So the naked return returns `estimated` automatically. *CORRECT*
2. return statement is not necessary there. Go automatically returns `estimated`.
3. Result values cannot have a name. This code is incorrect.
## Does the following code work? If so, why?
IT SHOULD PRINT: map[1:11 10:3]
```go
func main() {
stats := map[int]int{1: 10, 10: 2}
incrAll(stats)
fmt.Print(stats)
}
func incrAll(stats map[int]int) {
for k := range stats {
stats[k]++
}
}
```
1. No, it doesn't work: Go is a pass by value language. `incrAll` cannot update the map value.
2. Yes, it works: `incrAll` can update the map value. *CORRECT*
> **2:** Map values are pointers. So, `incrAll` can update the map value.
## Does the following code work? If so, why?
IT SHOULD PRINT: [10 5 2]
```go
func main() {
stats := []int{10, 5}
add(stats, 2)
fmt.Print(stats)
}
func add(stats []int, n int) {
stats = append(stats, n)
}
```
1. No, it doesn't work: `add()` cannot update the original slice header. *CORRECT*
2. Yes, it works: `add()` can add new element to the original slice header.
> **1:** Go is a pass-by-value programming language. add() creates a copy of the original slice header and adds the new element to the new slice header but it never returns the updated one. So, it cannot update the original slice header. It should have been returning the original slice header.
================================================
FILE: 26-pointers/01-pointers/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var counter byte = 100
P := &counter
V := *P
fmt.Printf("counter : %-16d address: %-16p\n", counter, &counter)
fmt.Printf("P : %-16p address: %-16p *P: %-16d\n", P, &P, *P)
fmt.Printf("V : %-16d address: %-16p\n", V, &V)
V = 200
fmt.Println()
fmt.Printf("counter : %-16d address: %-16p\n", counter, &counter)
fmt.Printf("P : %-16p address: %-16p *P: %-16d\n", P, &P, *P)
fmt.Printf("V : %-16d address: %-16p\n", V, &V)
V = counter // reset the V to counter's initial value
counter++
fmt.Println()
fmt.Printf("counter : %-16d address: %-16p\n", counter, &counter)
fmt.Printf("P : %-16p address: %-16p *P: %-16d\n", P, &P, *P)
fmt.Printf("V : %-16d address: %-16p\n", V, &V)
*P = 25
fmt.Println()
fmt.Printf("counter : %-16d address: %-16p\n", counter, &counter)
fmt.Printf("P : %-16p address: %-16p *P: %-16d\n", P, &P, *P)
fmt.Printf("V : %-16d address: %-16p\n", V, &V)
}
================================================
FILE: 26-pointers/02-pointers-basic-examples/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
counter int
V int
P *int
)
counter = 100 // counter is an int variable
P = &counter // P is a pointer int variable
V = *P // V is a int variable (a copy of counter)
if P == nil {
fmt.Printf("P is nil and its address is %p\n", P)
}
if P == &counter {
fmt.Printf("P is equal to counter's address: %p == %p\n",
P, &counter)
}
fmt.Printf("counter: %-13d addr: %-13p\n", counter, &counter)
fmt.Printf("P : %-13p addr: %-13p *P: %-13d\n", P, &P, *P)
fmt.Printf("V : %-13d addr: %-13p\n", V, &V)
fmt.Println("\n••••• change counter")
counter = 10 // V doesn't change because it's a copy
fmt.Printf("counter: %-13d addr: %-13p\n", counter, &counter)
fmt.Printf("V : %-13d addr: %-13p\n", V, &V)
fmt.Println("\n••••• change counter in passVal()")
counter = passVal(counter)
fmt.Printf("counter: %-13d addr: %-13p\n", counter, &counter)
fmt.Println("\n••••• change counter in passPtrVal()")
passPtrVal(&counter) // same as passPtrVal(&counter) (no need to return)
passPtrVal(&counter) // same as passPtrVal(&counter) (no need to return)
fmt.Printf("counter: %-13d addr: %-13p\n", counter, &counter)
}
// *pn is a int pointer variable (copy of P)
func passPtrVal(pn *int) {
fmt.Printf("pn : %-13p addr: %-13p *pn: %d\n", pn, &pn, *pn)
// pointers can breach function isolation borders
*pn++ // counter changes because `pn` points to `counter` — (*pn)++
fmt.Printf("pn : %-13p addr: %-13p *pn: %d\n", pn, &pn, *pn)
// setting it to nil doesn't effect the caller (the main function)
pn = nil
}
// n is a int variable (copy of counter)
func passVal(n int) int {
n = 50 // counter doesn't change because `n` is a copy
fmt.Printf("n : %-13d addr: %-13p\n", n, &n)
return n
}
================================================
FILE: 26-pointers/03-pointers-composites/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Println("••••• ARRAYS")
arrays()
fmt.Println("\n••••• SLICES")
slices()
fmt.Println("\n••••• MAPS")
maps()
fmt.Println("\n••••• STRUCTS")
structs()
}
// ••••••••••••••••••••••••••••••••••••••••••••••••••
type house struct {
name string
rooms int
}
func structs() {
myHouse := house{name: "My House", rooms: 5}
addRoom(myHouse)
// fmt.Printf("%+v\n", myHouse)
fmt.Printf("structs() : %p %+v\n", &myHouse, myHouse)
addRoomPtr(&myHouse)
fmt.Printf("structs() : %p %+v\n", &myHouse, myHouse)
}
func addRoomPtr(h *house) {
h.rooms++ // same: (*h).rooms++
fmt.Printf("addRoomPtr() : %p %+v\n", h, h)
fmt.Printf("&h.name : %p\n", &h.name)
fmt.Printf("&h.rooms : %p\n", &h.rooms)
}
func addRoom(h house) {
h.rooms++
fmt.Printf("addRoom() : %p %+v\n", &h, h)
}
// ••••••••••••••••••••••••••••••••••••••••••••••••••
func maps() {
confused := map[string]int{"one": 2, "two": 1}
fix(confused)
fmt.Println(confused)
// &confused["one"]
}
func fix(m map[string]int) {
m["one"] = 1
m["two"] = 2
m["three"] = 3
}
// ••••••••••••••••••••••••••••••••••••••••••••••••••
func slices() {
dirs := []string{"up", "down", "left", "right"}
up(dirs)
fmt.Printf("slices list : %p %q\n", &dirs, dirs)
upPtr(&dirs)
fmt.Printf("slices list : %p %q\n", &dirs, dirs)
}
func upPtr(list *[]string) {
lv := *list
for i := range lv {
lv[i] = strings.ToUpper(lv[i])
}
*list = append(*list, "HEISEN BUG")
fmt.Printf("upPtr list : %p %q\n", list, list)
}
func up(list []string) {
for i := range list {
list[i] = strings.ToUpper(list[i])
fmt.Printf("up.list[%d] : %p\n", i, &list[i])
}
list = append(list, "HEISEN BUG")
fmt.Printf("up list : %p %q\n", &list, list)
}
// ••••••••••••••••••••••••••••••••••••••••••••••••••
func arrays() {
nums := [...]int{1, 2, 3}
incr(nums)
fmt.Printf("arrays nums : %p\n", &nums)
fmt.Println(nums)
incrByPtr(&nums)
fmt.Println(nums)
}
func incr(nums [3]int) {
fmt.Printf("incr nums : %p\n", &nums)
for i := range nums {
nums[i]++
fmt.Printf("incr.nums[%d] : %p\n", i, &nums[i])
}
}
func incrByPtr(nums *[3]int) {
fmt.Printf("incrByPtr nums: %p\n", &nums)
for i := range nums {
nums[i]++ // same: (*nums)[i]++
}
}
================================================
FILE: 26-pointers/04-log-parser-pointers/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/04-log-parser-pointers/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/04-log-parser-pointers/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/04-log-parser-pointers/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/04-log-parser-pointers/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
func main() {
p := newParser()
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
parsed := parse(&p, in.Text())
update(&p, parsed)
}
summarize(p)
dumpErrs([]error{in.Err(), p.lerr})
}
// summarize summarizes and prints the parsing result
func summarize(p parser) {
sort.Strings(p.domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range p.domains {
parsed := p.sum[domain]
fmt.Printf("%-30s %10d\n", domain, parsed.visits)
}
// Print the total visits for all domains
fmt.Printf("\n%-30s %10d\n", "TOTAL", p.total)
}
// dumpErrs simplifies handling multiple errors
func dumpErrs(errs []error) {
for _, err := range errs {
if err != nil {
fmt.Println("> Err:", err)
}
}
}
================================================
FILE: 26-pointers/04-log-parser-pointers/parser.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
// result stores the parsed result for a domain
type result struct {
domain string
visits int
// add more metrics if needed
}
// parser keep tracks of the parsing
type parser struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total int // total visits for all domains
lines int // number of parsed lines (for the error messages)
lerr error // the last error occurred
}
// newParser constructs, initializes and returns a new parser
func newParser() parser {
return parser{sum: make(map[string]result)}
}
// parse parses a log line and returns the parsed result with an error
func parse(p *parser, line string) (parsed result) {
if p.lerr != nil {
return
}
p.lines++
fields := strings.Fields(line)
if len(fields) != 2 {
p.lerr = fmt.Errorf("wrong input: %v (line #%d)", fields, p.lines)
return
}
parsed.domain = fields[0]
var err error
parsed.visits, err = strconv.Atoi(fields[1])
if parsed.visits < 0 || err != nil {
p.lerr = fmt.Errorf("wrong input: %q (line #%d)", fields[1], p.lines)
}
return
}
// update updates all the parsing results using the given parsing result
func update(p *parser, parsed result) {
if p.lerr != nil {
return
}
domain, visits := parsed.domain, parsed.visits
// Collect the unique domains
if _, ok := p.sum[domain]; !ok {
p.domains = append(p.domains, domain)
}
// Keep track of total and per domain visits
p.total += visits
// create and assign a new copy of `visit`
p.sum[domain] = result{
domain: domain,
visits: visits + p.sum[domain].visits,
}
}
================================================
FILE: 26-pointers/05-log-parser-pointers-vs-values/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/05-log-parser-pointers-vs-values/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/05-log-parser-pointers-vs-values/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/05-log-parser-pointers-vs-values/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/05-log-parser-pointers-vs-values/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
func main() {
p := newParser()
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
parsed := parse(p, in.Text())
update(p, parsed)
}
summarize(p)
dumpErrs([]error{in.Err(), err(p)})
}
// summarize summarizes and prints the parsing result
func summarize(p *parser) {
sort.Strings(p.domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range p.domains {
fmt.Printf("%-30s %10d\n", domain, p.sum[domain].visits)
}
fmt.Printf("\n%-30s %10d\n", "TOTAL", p.total)
}
// dumpErrs simplifies handling multiple errors
func dumpErrs(errs []error) {
for _, err := range errs {
if err != nil {
fmt.Println("> Err:", err)
}
}
}
================================================
FILE: 26-pointers/05-log-parser-pointers-vs-values/parser.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
// result stores the parsed result for a domain
type result struct {
domain string
visits int
// add more metrics if needed
}
// parser keep tracks of the parsing
type parser struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total int // total visits for all domains
lines int // number of parsed lines (for the error messages)
lerr error // the last error occurred
}
// newParser constructs, initializes and returns a new parser
func newParser() *parser {
return &parser{sum: make(map[string]result)}
}
// parse parses a log line and returns the parsed result with an error
func parse(p *parser, line string) (r result) {
if p.lerr != nil {
return
}
p.lines++
fields := strings.Fields(line)
if len(fields) != 2 {
p.lerr = fmt.Errorf("wrong input: %v (line #%d)", fields, p.lines)
return
}
var err error
r.domain = fields[0]
r.visits, err = strconv.Atoi(fields[1])
if r.visits < 0 || err != nil {
p.lerr = fmt.Errorf("wrong input: %q (line #%d)", fields[1], p.lines)
}
return
}
// update updates all the parsing results using the given parsing result
func update(p *parser, r result) {
if p.lerr != nil {
return
}
// Collect the unique domains
if _, ok := p.sum[r.domain]; !ok {
p.domains = append(p.domains, r.domain)
}
// Keep track of total and per domain visits
p.total += r.visits
// create and assign a new copy of `visit`
p.sum[r.domain] = result{
domain: r.domain,
visits: r.visits + p.sum[r.domain].visits,
}
}
// err returns the last error encountered
func err(p *parser) error {
return p.lerr
}
================================================
FILE: 26-pointers/exercises/01-basics/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Basics
//
// Let's warm up with the pointer basics. Please follow the
// instructions inside the code. Run the solution to see
// its output if you need to.
// ---------------------------------------------------------
package main
type computer struct {
brand string
}
func main() {
// create a nil pointer with the type of pointer to a computer
// compare the pointer variable to a nil value, and say it's nil
// create an apple computer by putting its address to a pointer variable
// put the apple into a new pointer variable
// compare the apples: if they are equal say so and print their addresses
// create a sony computer by putting its address to a new pointer variable
// compare apple to sony, if they are not equal say so and print their
// addresses
// put apple's value into a new ordinary variable
// print apple pointer variable's address, and the address it points to
// and, print the new variable's addresses as well
// compare the value that is pointed by the apple and the new variable
// if they are equal say so
// print the values:
// the value that is pointed by the apple and the new variable
// create a new function: change
// the func can change the given computer's brand to another brand
// change sony's brand to hp using the func — print sony's brand
// write a func that returns the value that is pointed by the given *computer
// print the returned value
// write a new constructor func that returns a pointer to a computer
// and call the func 3 times and print the returned values' addresses
}
================================================
FILE: 26-pointers/exercises/01-basics/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type computer struct {
brand string
}
func main() {
// create a nil pointer with the type of pointer to a computer
var null *computer
// compare the pointer variable to a nil value
if null == nil {
// , and say it's nil
fmt.Println("null computer is nil")
}
// create an apple computer by putting its address to a pointer variable
apple := &computer{brand: "apple"}
// put the apple into a new pointer variable
newApple := apple
// compare the apples: if they are equal
if apple == newApple {
// say so and print their addresses
fmt.Printf("apples are equal : apple: %p newApple: %p\n",
apple, newApple)
}
// create a sony computer by putting its address to a new pointer variable
sony := &computer{brand: "sony"}
// compare apple to sony, if they are not equal
if apple != sony {
// say so and print their addresses
fmt.Printf("apple and sony are inequal: apple: %p sony: %p\n",
apple, sony)
}
// put apple's value into a new ordinary variable
appleVal := *apple
// print apple pointer variable's address, and the address it points to
// and, print the new variable's addresses as well
fmt.Printf("apple : %p %p\n", &apple, apple)
fmt.Printf("appleVal : %p\n", &appleVal)
// compare the value that is pointed by the apple and the new variable
if *apple == appleVal {
// if they are equal say so
fmt.Println("apple and appleVal are equal")
// print the values:
// the value that is pointed by the apple and the new variable
fmt.Printf("apple : %+v — appleVal: %+v\n",
*apple, appleVal)
}
// change sony's brand to hp using the func
change(sony, "hp")
// print sony's brand
fmt.Printf("sony : %s\n", sony.brand)
// print the returned value
fmt.Printf("appleVal : %+v\n", valueOf(apple))
// and call the func 3 times and print the returned values' addresses
fmt.Printf("dell's address : %p\n", newComputer("dell"))
fmt.Printf("lenovo's address : %p\n", newComputer("lenovo"))
fmt.Printf("acer's address : %p\n", newComputer("acer"))
}
// create a new function: change
// the func can change the given computer's brand to another brand
func change(c *computer, brand string) {
c.brand = brand
}
// write a func that returns the value that is pointed by the given *computer
func valueOf(c *computer) computer {
return *c
}
// write a new constructor func that returns a pointer to a computer
func newComputer(brand string) *computer {
return &computer{brand: brand}
}
================================================
FILE: 26-pointers/exercises/02-swap/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Swap
//
// Using funcs, swap values through pointers, and swap
// the addresses of the pointers.
//
//
// 1- Swap the values through a func
//
// a- Declare two float variables
//
// b- Declare a func that can swap the variables' values
// through their memory addresses
//
// c- Pass the variables' addresses to the func
//
// d- Print the variables
//
//
// 2- Swap the addresses of the float pointers through a func
//
// a- Declare two float pointer variables and,
// assign them the addresses of float variables
//
// b- Declare a func that can swap the addresses
// of two float pointers
//
// c- Pass the pointer variables to the func
//
// d- Print the addresses, and values that are
// pointed by the pointer variables
//
// ---------------------------------------------------------
package main
func main() {
}
================================================
FILE: 26-pointers/exercises/02-swap/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
a, b := 3.14, 6.28
swap(&a, &b)
fmt.Printf("a : %g — b : %g\n", a, b)
pa, pb := &a, &b
pa, pb = swapAddr(pa, pb)
fmt.Printf("pa: %p — pb: %p\n", pa, pb)
fmt.Printf("pa: %g — pb: %g\n", *pa, *pb)
}
func swap(a, b *float64) {
*a, *b = *b, *a
}
func swapAddr(a, b *float64) (*float64, *float64) {
return b, a
}
================================================
FILE: 26-pointers/exercises/03-fix-the-crash/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Fix the crash
//
// EXPECTED OUTPUT
//
// brand: apple
// ---------------------------------------------------------
package main
import "fmt"
type computer struct {
brand *string
}
func main() {
var c *computer
change(c, "apple")
fmt.Printf("brand: %s\n", c.brand)
}
func change(c *computer, brand string) {
(*c.brand) = brand
}
================================================
FILE: 26-pointers/exercises/03-fix-the-crash/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type computer struct {
brand *string
}
func main() {
c := &computer{} // init with a value (before: c was nil)
change(c, "apple")
fmt.Printf("brand: %s\n", *c.brand) // print the pointed value
}
func change(c *computer, brand string) {
c.brand = &brand // set the brand's address
}
================================================
FILE: 26-pointers/exercises/04-simplify/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// ---------------------------------------------------------
// EXERCISE: Simplify the code
// HINT : Remove the unnecessary pointer usages
// ---------------------------------------------------------
package main
import "fmt"
func main() {
var schools []map[int]string
schools = append(schools, make(map[int]string))
load(&schools[0], &([]string{"batman", "superman"}))
schools = append(schools, make(map[int]string))
load(&schools[1], &([]string{"spiderman", "wonder woman"}))
fmt.Println(schools[0])
fmt.Println(schools[1])
}
func load(m *map[int]string, students *[]string) {
for i, name := range *students {
(*m)[i+1] = name
}
}
================================================
FILE: 26-pointers/exercises/04-simplify/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
schools := make([]map[int]string, 2)
for i := range schools {
schools[i] = make(map[int]string)
}
load(schools[0], []string{"batman", "superman"})
load(schools[1], []string{"spiderman", "wonder woman"})
fmt.Println(schools[0])
fmt.Println(schools[1])
}
func load(m map[int]string, students []string) {
for i, name := range students {
m[i+1] = name
}
}
================================================
FILE: 26-pointers/exercises/05-log-parser/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/exercises/05-log-parser/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/exercises/05-log-parser/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/exercises/05-log-parser/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: 26-pointers/exercises/05-log-parser/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
func main() {
p := newParser()
// Scan the standard-in line by line
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
p.lines++
parsed, err := parse(p, in.Text())
if err != nil {
fmt.Println(err)
return
}
p = update(p, parsed)
}
// Print the visits per domain
sort.Strings(p.domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range p.domains {
parsed := p.sum[domain]
fmt.Printf("%-30s %10d\n", domain, parsed.visits)
}
// Print the total visits for all domains
fmt.Printf("\n%-30s %10d\n", "TOTAL", p.total)
// Let's handle the error
if err := in.Err(); err != nil {
fmt.Println("> Err:", err)
}
}
================================================
FILE: 26-pointers/exercises/05-log-parser/parser.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
// result stores the parsed result for a domain
type result struct {
domain string
visits int
// add more metrics if needed
}
// parser keep tracks of the parsing
type parser struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total int // total visits for all domains
lines int // number of parsed lines (for the error messages)
}
// newParser constructs, initializes and returns a new parser
func newParser() parser {
return parser{sum: make(map[string]result)}
}
// parse parses a log line and returns the parsed result with an error
func parse(p parser, line string) (parsed result, err error) {
fields := strings.Fields(line)
if len(fields) != 2 {
err = fmt.Errorf("wrong input: %v (line #%d)", fields, p.lines)
return
}
parsed.domain = fields[0]
parsed.visits, err = strconv.Atoi(fields[1])
if parsed.visits < 0 || err != nil {
err = fmt.Errorf("wrong input: %q (line #%d)", fields[1], p.lines)
return
}
return
}
// update updates the parser for the given parsing result
func update(p parser, parsed result) parser {
domain, visits := parsed.domain, parsed.visits
// Collect the unique domains
if _, ok := p.sum[domain]; !ok {
p.domains = append(p.domains, domain)
}
// Keep track of total and per domain visits
p.total += visits
// create and assign a new copy of `visit`
p.sum[domain] = result{
domain: domain,
visits: visits + p.sum[domain].visits,
}
return p
}
================================================
FILE: 26-pointers/exercises/README.md
================================================
# Pointer Exercises
1. **[Basics](https://github.com/inancgumus/learngo/tree/master/26-pointers/exercises/01-basics)**
Warm-up and solidify your knowledge of pointers with the basic exercises. This exercise contains 10+ mini exercises in itself.
2. **[Swap](https://github.com/inancgumus/learngo/tree/master/26-pointers/exercises/02-swap)**
Using funcs, swap the values through pointers, and swap the addresses of pointers. It may be tricky than it sounds.
3. **[Fix the Crash](https://github.com/inancgumus/learngo/tree/master/26-pointers/exercises/03-fix-the-crash)**
Fix the crashing program. Another tricky exercise.
4. **[Simplify](https://github.com/inancgumus/learngo/tree/master/26-pointers/exercises/04-simplify)**
Simplify the given code using your knowledge of map, slices, and pointers.
5. **[Rewrite the Log Parser program using pointers](https://github.com/inancgumus/learngo/tree/master/26-pointers/exercises/05-log-parser)**
You've watched the lecture. Now, try to rewrite the same log parser program using pointers on your own.
================================================
FILE: 26-pointers/questions/README.md
================================================
## What is a pointer?
1. A variable that contains an hexadecimal value
2. A variable that contains a memory address
3. A value that can contain a memory address of a value *CORRECT*
4. A value that points to a function
> **2:** Although a pointer can be put into a variable, it's not solely a variable. You're almost there! But this distinction is very important.
>
> **3:** A pointer is just another value that can contain a memory address of a value.
## Which one is a pointer to a computer?
```go
type computer struct {
brand string
}
```
1. `*computer{}`
2. `var c computer`
3. `var *c computer`
4. `var c *computer` *CORRECT*
> **4:** * in front of a type denotes a pointer type.
## Which one gets the pointed composite value by the following pointer?
```go
type computer struct {
brand string
}
c := &computer{"Apple"}
```
1. `*c` *CORRECT*
2. `&c`
3. `c`
4. `*computer`
> **1:** * in front of a pointer value gets the value that is pointed by the pointer.
>
> **2:** & in front of a value gets the memory address of that value
>
> **4:** * in front of a type denotes a pointer type.
## What is the result of the following code?
```go
type computer struct {
brand string
}
var a, b *computer
fmt.Print(a == b)
a = &computer{"Apple"}
b = &computer{"Apple"}
fmt.Print(" ", a == b, " ", *a == *b)
```
1. false false false
2. true true true
3. true false true *CORRECT*
4. false true true
> **3:** a and b are nil at the beginning, so they are equal. However, after that, they get two different memory addresses from the composite literals, so their addresses are not equal but their values (that are pointed by the pointers) are equal.
## How many variables are there in the following code?
```go
type computer struct {
brand string
}
func main() {
a = &computer{"Apple"}
b := a
change(b)
change(b)
}
func change(c *computer) {
c.brand = "Indie"
c = nil
}
```
1. 1
2. 2
3. 3
4. 4 *CORRECT*
> **4:** Every time a func runs, it creates new variables from its input params and named result values (if any). There two pointer variables: a and b. Then there are, two more pointer variables because: change is called two times.
## Why you cannot take the address of a map's elements?
1. It's an addressable value
2. It's an unaddressable value *CORRECT*
3. Doing so can crash your program
> **2:** Map elements are not addressable, so you cannot take their addresses.
================================================
FILE: LICENSE
================================================
Copyright (c) 2018 Inanc Gumus
=======================================================================
Attribution-NonCommercial-ShareAlike 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-NonCommercial-ShareAlike 4.0 International Public License
("Public License"). To the extent this Public License may be
interpreted as a contract, You are granted the Licensed Rights in
consideration of Your acceptance of these terms and conditions, and the
Licensor grants You such rights in consideration of benefits the
Licensor receives from making the Licensed Material available under
these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-NC-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution, NonCommercial, and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. NonCommercial means not primarily intended for or directed towards
commercial advantage or monetary compensation. For purposes of
this Public License, the exchange of the Licensed Material for
other material subject to Copyright and Similar Rights by digital
file-sharing or similar means is NonCommercial provided there is
no payment of monetary compensation in connection with the
exchange.
l. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
m. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
n. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part, for NonCommercial purposes only; and
b. produce, reproduce, and Share Adapted Material for
NonCommercial purposes only.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties, including when
the Licensed Material is used other than for NonCommercial
purposes.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-NC-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database for NonCommercial purposes
only;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.
For more information, see: https://creativecommons.org/licenses/by-nc-sa/4.0/
=======================================================================
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
================================================
FILE: README.md
================================================
# Want to go beyond the basics? Get my book! ✨
Go by Example: Programmer's guide to idiomatic and testable code.
👉 https://github.com/inancgumus/gobyexample
[](https://github.com/inancgumus/gobyexample)
---
# A Huge Number of Go Examples, Exercises, and Quizzes
The best way to learn is by doing. Inside this repository, you will find thousands of Go examples, exercises, and quizzes. I initially created this repository for my **[Go: Bootcamp Course](https://www.udemy.com/course/learn-go-the-complete-bootcamp-course-golang/?referralCode=5CE6EB34E2B1EF4A7D37)**. Later, I added a lot of exercises, and I wanted every programmer who is not yet enrolled in the course to learn for free as well. So here it is. Enjoy.
**Available in the following languages:**
* **[English](https://github.com/inancgumus/learngo)**
* **[Spanish](translation/spanish)** _(WIP: Please Contribute)_
* **[Chinese](translation/chinese)** _(WIP: Please Contribute)_
## ❤️ Help other fellow developers
Sharing is free, but caring is priceless. [So, now please click here](https://twitter.com/intent/tweet?text=I%27m%20learning%20%23golang%20with%201000%2B%20hand-crafted%20examples%2C%20exercises%2C%20and%20quizzes.&url=https://github.com/inancgumus/learngo&via=inancgumus) and share this repository on Twitter.
## Stay in touch
* **[Follow me on Twitter](https://twitter.com/inancgumus)**
_I usually tweet Go tips and tricks._
[](https://twitter.com/inancgumus)
* **[Subscribe to my newsletter](https://eepurl.com/c4DMNX)**
_Get updates from me._
* **[Read my blog](https://blog.learngoprogramming.com)**
_Followed by 5K+ developers, and contains dozens of illustrated articles about Go._
* **[Watch my Youtube channel](https://www.youtube.com/channel/UCYxepZhtnFIVRh8t5H_QAdg?view_as=subscriber)**
---
## License
Whole materials are licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
================================================
FILE: advfuncs/01-variadic-funcs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
nums := []int{2, 3, 7}
fmt.Printf("nums : %d\n", nums)
n := avgNoVariadic(nums)
fmt.Printf("avgNoVariadic : %d\n", n)
n = avg(2, 3, 7)
fmt.Printf("avg(2, 3, 7) : %d\n", n)
n = avg(2, 3, 7, 8)
fmt.Printf("avg(2, 3, 7, 8) : %d\n", n)
// use ... to pass a slice
n = avg(nums...)
fmt.Printf("avg(nums...) : %d\n", n)
// uses the existing slice
double(nums...)
fmt.Printf("double(nums...) : %d\n", nums)
// creates a new slice
double(4, 6, 14)
fmt.Printf("double(4, 6, 14): %d\n", nums)
// creates a nil slice
fmt.Printf("\nmain.nums : %p\n", nums)
investigate("passes main.nums", nums...)
investigate("passes main.nums", nums...)
investigate("passes args", 4, 6, 14)
investigate("passes args", 4, 6, 14)
investigate("no args")
}
func investigate(msg string, nums ...int) {
fmt.Printf("investigate.nums: %12p -> %s\n", nums, msg)
if len(nums) > 0 {
fmt.Printf("\tfirst element: %d\n", nums[0])
}
}
func double(nums ...int) {
for i := range nums {
nums[i] *= 2
}
}
func avg(nums ...int) int {
return sum(nums) / len(nums)
}
func avgNoVariadic(nums []int) int {
return sum(nums) / len(nums)
}
func sum(nums []int) (total int) {
for _, n := range nums {
total += n
}
return
}
================================================
FILE: advfuncs/02-func-values/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type filterFunc func(int) bool
func main() {
signatures()
funcValues()
}
func isEven(n int) bool {
return n%2 == 0
}
func isOdd(m int) bool {
return m%2 == 1
}
func signatures() {
fmt.Println("••• FUNC SIGNATURES (TYPES) •••")
fmt.Printf("isEven : %T\n", isEven)
fmt.Printf("isOdd : %T\n", isOdd)
}
func funcValues() {
fmt.Println("\n••• FUNC VALUES (VARS) •••")
// var value func(int) bool
var value filterFunc
fmt.Printf("value nil? : %t\n", value == nil)
value = isEven
fmt.Printf("value(2) : %t\n", value(2))
fmt.Printf("isEven(2) : %t\n", isEven(2))
value = isOdd
fmt.Printf("value(1) : %t\n", value(1))
fmt.Printf("isOdd(1) : %t\n", isOdd(1))
fmt.Printf("value nil? : %t\n", value == nil)
fmt.Printf("value : %p\n", value)
fmt.Printf("isEven : %p\n", isEven)
fmt.Printf("isOdd : %p\n", isOdd)
}
================================================
FILE: advfuncs/03-func-to-func/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
"unicode"
)
type filterFunc func(int) bool
func main() {
signatures()
fmt.Println("\n••• WITHOUT FUNC VALUES •••")
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Printf("evens : %d\n", filterEvens(nums...))
fmt.Printf("odds : %d\n", filterOdds(nums...))
fmt.Println("\n••• FUNC VALUES •••")
fmt.Printf("evens : %d\n", filter(isEven, nums...))
fmt.Printf("odds : %d\n", filter(isOdd, nums...))
fmt.Println("\n••• MAPPING •••")
fmt.Println(strings.Map(unpunct, "hello!!! HOW ARE YOU???? :))"))
fmt.Println(strings.Map(unpunct, "TIME IS UP!"))
}
func unpunct(r rune) rune {
if unicode.IsPunct(r) {
return -1
}
return unicode.ToLower(r)
}
func filter(f filterFunc, nums ...int) (filtered []int) {
for _, n := range nums {
if f(n) {
filtered = append(filtered, n)
}
}
return
}
func filterOdds(nums ...int) (filtered []int) {
for _, n := range nums {
if isOdd(n) {
filtered = append(filtered, n)
}
}
return
}
func filterEvens(nums ...int) (filtered []int) {
for _, n := range nums {
if isEven(n) {
filtered = append(filtered, n)
}
}
return
}
func isEven(n int) bool {
return n%2 == 0
}
func isOdd(m int) bool {
return m%2 == 1
}
func signatures() {
fmt.Println("••• FUNC SIGNATURES (TYPES) •••")
fmt.Printf("isEven : %T\n", isEven)
fmt.Printf("isOdd : %T\n", isOdd)
}
================================================
FILE: advfuncs/04-closures/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type filterFunc func(int) bool
func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Println("••• FUNC VALUES •••")
fmt.Printf("evens : %d\n", filter(isEven, nums...))
fmt.Printf("odds : %d\n", filter(isOdd, nums...))
fmt.Printf("> 3 : %d\n", filter(greaterThan3, nums...))
fmt.Printf("> 6 : %d\n", filter(greaterThan6, nums...))
// ========================================================================
fmt.Println("\n••• CLOSURES •••")
var min int
greaterThan := func(n int) bool {
return n > min
}
min = 3
fmt.Printf("> 3 : %d\n", filter(greaterThan, nums...))
min = 6
fmt.Printf("> 6 : %d\n", filter(greaterThan, nums...))
// min = 1
// fmt.Printf("> 1 : %d\n", filter(greaterThan, nums...))
// min = 2
// fmt.Printf("> 2 : %d\n", filter(greaterThan, nums...))
// min = 3
// fmt.Printf("> 3 : %d\n", filter(greaterThan, nums...))
var filterers []filterFunc
for i := 1; i <= 3; i++ {
current := i
filterers = append(filterers, func(n int) bool {
min = current
return greaterThan(n)
})
}
printer(filterers, nums...)
}
func printer(filterers []filterFunc, nums ...int) {
for i, filterer := range filterers {
fmt.Printf("> %d : %d\n", i+1, filter(filterer, nums...))
}
}
func greaterThan6(n int) bool { return n > 6 }
func greaterThan3(n int) bool { return n > 3 }
func isEven(n int) bool { return n%2 == 0 }
func isOdd(m int) bool { return m%2 == 1 }
func filter(f filterFunc, nums ...int) (filtered []int) {
for _, n := range nums {
if f(n) {
filtered = append(filtered, n)
}
}
return
}
================================================
FILE: advfuncs/05-higher-order-funcs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
type filterFunc func(int) bool
func main() {
fmt.Println("••• HIGHER-ORDER FUNCS •••")
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
odd := reverse(reverse(isEven))
fmt.Printf("reversed : %t\n", odd(8))
fmt.Printf("> 3 : %d\n", filter(greater(3), nums...))
fmt.Printf("> 6 : %d\n", filter(greater(6), nums...))
fmt.Printf("<= 6 : %d\n", filter(lesseq(6), nums...))
fmt.Printf("<= 6 : %d\n", filter(reverse(greater(6)), nums...))
}
func reverse(f filterFunc) filterFunc {
return func(n int) bool {
return !f(n)
}
}
func greater(min int) filterFunc {
return func(n int) bool {
return n > min
}
}
func lesseq(max int) filterFunc {
return func(n int) bool {
return n <= max
}
}
func filter(f filterFunc, nums ...int) (filtered []int) {
for _, n := range nums {
if f(n) {
filtered = append(filtered, n)
}
}
return
}
func isEven(n int) bool { return n%2 == 0 }
func isOdd(m int) bool { return m%2 == 1 }
================================================
FILE: advfuncs/06-functional-programming/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
type filterFunc func(int) bool
func main() {
fmt.Println("••• HIGHER-ORDER FUNCS •••")
nums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
odd := reverse(reverse(isEven))
fmt.Printf("reversed : %t\n", odd(8))
fmt.Printf("> 3 : %d\n", filter(greater(3), nums...))
fmt.Printf("> 6 : %d\n", filter(greater(6), nums...))
fmt.Printf("<= 6 : %d\n", filter(lesseq(6), nums...))
fmt.Printf("<= 6 : %d\n", filter(reverse(greater(6)), nums...))
fmt.Println("\n••• CLOSURES •••")
fmt.Printf("uniques : %d\n", filter(uniques(), 1, 1, 2, 3, 3))
dups := reverse(uniques())
fmt.Printf("dups : %v\n", filter(dups, 1, 1, 2, 3, 3))
dups = reverse(uniques())
fmt.Printf("dups dups : %v\n", filter(dups, 1, 1, 2, 3, 3, 3, 3))
dups = reverse(uniques())
out := filter(dups, 1, 1, 2, 3, 3, 3, 3)
fmt.Printf("dups uniqs : %v\n", filter(uniques(), out...))
dups = reverse(uniques())
chained := chain(reverse(greater(1)), dups, uniques())
fmt.Printf("dups chain : %v\n", filter(chained, 1, 1, 2, 3, 3, 3, 3, 0, 0))
}
func chain(filters ...filterFunc) filterFunc {
return func(n int) bool {
for _, next := range filters {
if !next(n) {
return false
}
}
return true
}
}
func uniques() filterFunc {
seen := make(map[int]bool)
return func(n int) (ok bool) {
if !seen[n] {
seen[n], ok = true, true
}
return
}
}
func reverse(f filterFunc) filterFunc {
return func(n int) bool {
return !f(n)
}
}
func greater(min int) filterFunc {
return func(n int) bool {
return n > min
}
}
func lesseq(max int) filterFunc {
return func(n int) bool {
return n <= max
}
}
func filter(f filterFunc, nums ...int) (filtered []int) {
for _, n := range nums {
if f(n) {
filtered = append(filtered, n)
}
}
return
}
func isEven(n int) bool { return n%2 == 0 }
func isOdd(m int) bool { return m%2 == 1 }
================================================
FILE: advfuncs/07-deferred-funcs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
// single()
// stacked()
findTheMeaning()
}
func findTheMeaningNoDefer() {
start := time.Now()
fmt.Printf("%s starts...\n", "findTheMeaning")
// do some heavy calculation...
time.Sleep(time.Second * 2)
fmt.Printf("%s took %v\n", "findTheMeaning", time.Since(start))
}
func findTheMeaning() {
defer measure("findTheMeaning")()
// do some heavy calculation
time.Sleep(time.Second * 2)
}
func measure(name string) func() {
start := time.Now()
fmt.Printf("%s starts...\n", name)
return func() {
fmt.Printf("%s took %v\n", name, time.Since(start))
}
}
func stacked() {
for count := 1; count <= 5; count++ {
defer fmt.Println(count)
}
fmt.Println("the stacked func returns")
}
func single() {
var count int
// defer func() {
// fmt.Println(count)
// }()
defer fmt.Println(count)
count++
// fmt.Println(count)
// the defer runs here
// fmt.Println(count)
}
================================================
FILE: advfuncs/08-png-detector/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"fmt"
"io"
"os"
)
func main() {
files := []string{
"pngs/cups-jpg.png",
"pngs/forest-jpg.png",
"pngs/golden.png",
"pngs/work.png",
"pngs/shakespeare-text.png",
"pngs/empty.png",
}
valids := detect(files)
fmt.Printf("Correct Files:\n")
for _, valid := range valids {
fmt.Printf(" + %s\n", valid)
}
}
func detect(filenames []string) (pngs []string) {
const pngHeader = "\x89PNG\r\n\x1a\n"
buf := make([]byte, len(pngHeader))
for _, filename := range filenames {
if read(filename, buf) != nil {
continue
}
if bytes.Equal([]byte(pngHeader), buf) {
pngs = append(pngs, filename)
}
}
return
}
// read reads len(buf) bytes to buf from a file
func read(filename string, buf []byte) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
fi, err := file.Stat()
if err != nil {
return err
}
if fi.Size() <= int64(len(buf)) {
return fmt.Errorf("file size < len(buf)")
}
_, err = io.ReadFull(file, buf)
return err
}
func detectPNGUnsafeAndVerbose(filenames []string) (valids []string) {
const pngHeader = "\x89PNG\r\n\x1a\n"
buf := make([]byte, len(pngHeader))
for _, filename := range filenames {
file, err := os.Open(filename)
if err != nil {
continue
}
fi, err := file.Stat()
if err != nil {
file.Close()
continue
}
if fi.Size() <= int64(len(pngHeader)) {
file.Close()
continue
}
_, err = io.ReadFull(file, buf)
file.Close()
if err != nil {
continue
}
if bytes.Equal([]byte(pngHeader), buf) {
valids = append(valids, filename)
}
}
return
}
// defers don't run when the loop block ends
func detectPNGWrong(filenames []string) (pngs []string) {
const pngHeader = "\x89PNG\r\n\x1a\n"
buf := make([]byte, len(pngHeader))
for _, filename := range filenames {
fmt.Printf("processing: %s\n", filename)
file, err := os.Open(filename)
if err != nil {
continue
}
defer func() {
fmt.Printf("closes : %s\n", filename)
file.Close()
}()
fi, err := file.Stat()
if err != nil {
continue
}
if fi.Size() <= int64(len(pngHeader)) {
continue
}
_, err = io.ReadFull(file, buf)
if err != nil {
continue
}
if bytes.Equal([]byte(pngHeader), buf) {
pngs = append(pngs, filename)
}
}
return
}
================================================
FILE: advfuncs/08-png-detector-with-panic/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"fmt"
"io"
"os"
)
/*
// ~~~ THE CLASSIC WAY ~~~
try {
// open a file
// throws an exception
} catch (ExceptionType name) {
// handle the error
} finally {
// close the file
}
// ~~~ GO WAY ~~~
file, err := // open the file
if err != nil {
// handle the error
}
// close the file
// really really exceptional problem occurs
// mostly due to a programmer
// panic("PANIC PANIC")
*/
func main() {
files := []string{
"pngs/cups-jpg.png",
"pngs/forest-jpg.png",
"pngs/golden.png",
"pngs/work.png",
"pngs/shakespeare-text.png",
"pngs/empty.png",
}
list("png", files)
// fmt.Println("catch me if you can!")
}
func list(format string, files []string) {
valids := detect(format, files)
fmt.Printf("Correct Files:\n")
for _, valid := range valids {
fmt.Printf(" + %s\n", valid)
}
}
func detect(format string, filenames []string) (valids []string) {
header := headerOf(format)
buf := make([]byte, len(header))
for _, filename := range filenames {
if read(filename, buf) != nil {
continue
}
if bytes.Equal([]byte(header), buf) {
valids = append(valids, filename)
}
}
return
}
func headerOf(format string) string {
switch format {
case "png":
return "\x89PNG\r\n\x1a\n"
case "jpg":
return "\xff\xd8\xff"
}
panic("unknown format: " + format)
}
// read reads len(buf) bytes to buf from a file
func read(filename string, buf []byte) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
fi, err := file.Stat()
if err != nil {
return err
}
if fi.Size() <= int64(len(buf)) {
return fmt.Errorf("file size < len(buf)")
}
_, err = io.ReadFull(file, buf)
return err
}
================================================
FILE: advfuncs/10-image-detector-recover/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"fmt"
"io"
"os"
)
func main() {
defer func() {
if rerr := recover(); rerr != nil {
fmt.Println("panicked:", rerr)
}
}()
files := []string{
"pngs/cups-jpg.png",
"pngs/forest-jpg.png",
"pngs/golden.png",
"pngs/work.png",
"pngs/shakespeare-text.png",
"pngs/empty.png",
}
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("png or jpg?")
return
}
list(args[0], files)
// fmt.Println("catch me if you can!")
}
func list(format string, files []string) {
valids := detect(format, files)
fmt.Printf("Correct Files:\n")
for _, valid := range valids {
fmt.Printf(" + %s\n", valid)
}
}
func detect(format string, filenames []string) (pngs []string) {
header := headerOf(format)
buf := make([]byte, len(header))
for _, filename := range filenames {
if read(filename, buf) != nil {
continue
}
if bytes.Equal([]byte(header), buf) {
pngs = append(pngs, filename)
}
}
return
}
func headerOf(format string) string {
switch format {
case "png":
return "\x89PNG\r\n\x1a\n"
case "jpg":
return "\xff\xd8\xff"
}
// this should never occur
panic("unknown format: " + format)
}
// read reads len(buf) bytes to buf from a file
func read(filename string, buf []byte) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
fi, err := file.Stat()
if err != nil {
return err
}
if fi.Size() <= int64(len(buf)) {
return fmt.Errorf("file size < len(buf)")
}
_, err = io.ReadFull(file, buf)
return err
}
================================================
FILE: advfuncs/10b-named-params/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"github.com/inancgumus/learngo/magic"
//
// Use the following one for the panicking library:
// magic "github.com/inancgumus/learngo/magicpanic"
//
)
func main() {
files := []string{
"pngs/cups-jpg.png",
"pngs/forest-jpg.png",
"pngs/golden.png",
"pngs/work.png",
"pngs/shakespeare-text.png",
"pngs/empty.png",
}
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("png or jpg?")
return
}
list(args[0], files)
// fmt.Println("catch me if you can!")
}
func list(format string, files []string) {
valids, err := magic.Detect(format, files)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Correct Files:\n")
for _, valid := range valids {
fmt.Printf(" + %s\n", valid)
}
}
================================================
FILE: advfuncs/exercises/01-refactor/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// EXERCISE: Refactor
//
// In the headerOf function, instead of using a switch,
// use a map. Declare it at the package-level.
//
// RESTRICTION
//
// For panicking, use a deferred function and a named param.
//
// EXPECTED OUTPUT
//
// Please run the solution.
//
// ---------------------------------------------------------
func main() {
fmt.Println(headerOf("gif"))
}
func headerOf(format string) string {
switch format {
case "png":
return "\x89PNG\r\n\x1a\n"
case "jpg":
return "\xff\xd8\xff"
}
panic("unknown format: " + format)
}
================================================
FILE: advfuncs/exercises/01-refactor/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println(headerOf("gif"))
}
var headers = map[string]string{
"png": "\x89PNG\r\n\x1a\n",
"jpg": "\xff\xd8\xff",
}
func headerOf(format string) (header string) {
defer func() {
if header == "" {
panic("unknown format: " + format)
}
}()
return headers[format]
}
================================================
FILE: advfuncs/exercises/README.md
================================================
# Header
What you will learn?
1. **[Refactor](https://github.com/inancgumus/learngo/tree/master/28-error-handling/exercises/01-refactor)**
Refactor the headerOf function with a map + defer + and a named param.
2. **[text](https://github.com/inancgumus/learngo/tree/master/)**
text
================================================
FILE: advfuncs/new/01-intro/funcval/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
func main() {
fmt.Printf("HasPrefix: %T\n", strings.HasPrefix)
fmt.Printf("HasSuffix: %T\n", strings.HasSuffix)
fmt.Println()
var fn func(string, string) bool
fn = strings.HasPrefix
fn = strings.HasSuffix
ok := fn("gopher", "go")
fmt.Printf("ok : %t\n", ok)
}
================================================
FILE: advfuncs/new/01-intro/passfunc/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"unicode"
)
func main() {
s := "Func Values Are Awesome..."
// s = strings.Map(unicode.ToUpper, s)
// s = strings.Map(unicode.ToLower, s)
// s = strings.Map(excite, s)
// s = strings.Map(calm, s)
// fmt.Printf("%T\n", strings.Map)
s = mapx(calm, s)
fmt.Println(s)
}
func mapx(mapping func(rune) rune, s string) string {
var ns []rune
for _, r := range s {
if r = mapping(r); r == -1 {
continue
}
ns = append(ns, r)
}
return string(ns)
}
func calm(r rune) rune {
if unicode.IsPunct(r) {
return -1
}
return unicode.ToLower(r)
}
func excite(r rune) rune {
if r == '.' {
return '!'
}
return unicode.ToTitle(r)
}
================================================
FILE: assets/database.json
================================================
[
{
"Type": "book",
"Item": {
"Title": "moby dick",
"Price": 10,
"Published": 118281600
}
},
{
"Type": "book",
"Item": {
"Title": "odyssey",
"Price": 15,
"Published": 733622400
}
},
{
"Type": "book",
"Item": {
"Title": "hobbit",
"Price": 25,
"Published": -62135596800
}
},
{
"Type": "puzzle",
"Item": {
"Title": "rubik's cube",
"Price": 5
}
},
{
"Type": "game",
"Item": {
"Title": "minecraft",
"Price": 20
}
},
{
"Type": "game",
"Item": {
"Title": "tetris",
"Price": 5
}
},
{
"Type": "toy",
"Item": {
"Title": "yoda",
"Price": 150
}
}
]
================================================
FILE: concurrency/xxx-monte-carlo/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
"math/rand"
"os"
"runtime"
"strconv"
"time"
)
func main() {
if len(os.Args) != 2 {
exit("Please provide the sample rate")
}
samples, err := strconv.Atoi(os.Args[1])
if err != nil {
exit("Incorrect sample rate")
}
elapse := measure(time.Now())
pi := spread(samples, runtime.NumCPU())
fmt.Println("PI : ", pi)
fmt.Println("Time: ", elapse())
}
func exit(msg string) {
fmt.Fprintln(os.Stderr, msg)
os.Exit(1)
}
func measure(start time.Time) func() time.Duration {
return func() time.Duration {
return time.Since(start)
}
}
// spread the work to P number of estimate go funcs.
// returns the estimation.
func spread(samples int, P int) (estimated float64) {
counts := make(chan float64)
for i := 0; i < P; i++ {
go func() { counts <- estimate(samples / P) }()
}
for i := 0; i < P; i++ {
estimated += <-counts
}
return estimated / float64(P)
}
func estimate(N int) float64 {
const radius = 1.0
var (
seed = rand.NewSource(time.Now().UnixNano())
random = rand.New(seed)
inside int
)
for i := 0; i < N; i++ {
x, y := random.Float64(), random.Float64()
if num := math.Sqrt(x*x + y*y); num < radius {
inside++
}
}
return 4 * float64(inside) / float64(N)
}
================================================
FILE: etc/FIX.md
================================================
# Things to fix
- [ ] AliasedTypes: At 4:48, `runVal = rune(int32Val)` [Ref](https://www.udemy.com/learn-go-the-complete-bootcamp-course-golang/learn/v4/questions/5603536)
- [ ] Underlying types demo gram/kilogram/ton confusion [Ref](https://www.udemy.com/learn-go-the-complete-bootcamp-course-golang/learn/v4/questions/5603348)
- [ ] Multiplication table challenge exercises flyer [Ref](https://www.udemy.com/learn-go-the-complete-bootcamp-course-golang/learn/v4/questions/5600066)
- [ ] Apply grammar mistakes to Udemy [Ref](https://github.com/inancgumus/learngo/commit/06891c57fc5299db5f5178bde4da7dd8e569c082)
- [ ] Fix the printing lecture 78 exercise (numbers) [Ref](https://learngoprogramming.slack.com/archives/DC86N4QJK/p1542552870174800)
- [ ] Fix the strings quiz [Ref](https://learngoprogramming.slack.com/archives/DC86N4QJK/p1542566248185500)
- [ ] Type conversion lecture doesn't talk about literal conversion but it asks a question as if it's been explained [Ref](https://www.udemy.com/message/thread/120614366/)
- [ ] Underlying types conversion possible misundertanding [Ref](https://twitter.com/in_aanand/status/1065136567629553664)
- [ ] Comment: Gram vs Gram1 — He's asking Gram1 should have been clearer. Explain this in the video. If it was Gram1 then the example would be pointless.
================================================
FILE: etc/stratch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// LearnGoProgramming.com ⭐️ @inancgumus
package main
func main() {
}
================================================
FILE: first/README.md
================================================
**The course videos follow this directory.**
So, you can find the lecture files in the same place as they are explained in the course videos. But then I've moved them into their own directories. This directory is here just for your convenience.
---
# ☢️ USE THE FOLLOWING DIRECTORIES INSTEAD! ☢️
**For the first part of the course; only the following directories contains exercises and quizzes.**
* [01-get-started/](https://github.com/inancgumus/learngo/tree/master/01-get-started)
* [02-write-your-first-program/](https://github.com/inancgumus/learngo/tree/master/02-write-your-first-program)
* [03-packages-and-scopes/](https://github.com/inancgumus/learngo/tree/master/03-packages-and-scopes)
* [04-statements-expressions-comments/](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments)
* [05-write-your-first-library-package/](https://github.com/inancgumus/learngo/tree/master/05-write-your-first-library-package)
================================================
FILE: first/explain/comments/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// Package main makes this package an executable program
package main
import "fmt"
/*
main function
Go executes this program using this function.
There should be only one main file in the main package.
Executable programs are also called as "commands".
*/
func main() {
fmt.Println("Hello Gopher!")
}
================================================
FILE: first/explain/expressions/01-operator/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello!" + "!")
}
================================================
FILE: first/explain/expressions/02-call-expression/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"runtime"
)
func main() {
// runtime.NumCPU() is a call expression
fmt.Println(runtime.NumCPU() + 1)
}
================================================
FILE: first/explain/expressions/README
================================================
I've moved the main.go file for the expressions coding lecture into:
02-call-expression/
================================================
FILE: first/explain/importing/01-file-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
}
================================================
FILE: first/explain/importing/02-renaming/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
import f "fmt"
func main() {
fmt.Println("Hello!")
f.Println("There!")
}
================================================
FILE: first/explain/packages/scopes/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("Bye!")
}
================================================
FILE: first/explain/packages/scopes/hey.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hey() {
fmt.Println("Hey!")
}
================================================
FILE: first/explain/packages/scopes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
// two files belong to the same package
// calling `bye()` of bye.go here
bye()
}
// EXERCISE: Remove the comments from the below function
// And analyze the error message
// func bye() {
// fmt.Println("Bye!")
// }
// ***** EXPLANATION *****
//
// ERROR: "bye" function "redeclared"
// in "this block"
//
// "this block" means = "main package"
//
// "redeclared" means = you're using the same name
// in the same scope again
//
// main package's scope is:
// all source-code files which are in the same main package
================================================
FILE: first/explain/packages/what/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("Bye!")
}
================================================
FILE: first/explain/packages/what/hey.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hey() {
fmt.Println("Hey!")
}
================================================
FILE: first/explain/packages/what/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
// You can access functions from other files
// which are in the same package
// Here, `main()` can access `bye()` and `hey()`
// It's because bye.go, hey.go and main.go
// are in the main package.
bye()
hey()
}
================================================
FILE: first/explain/scopes/01-scopes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// file scope
import "fmt"
// package scope
const ok = true
// package scope
func main() { // block scope starts
var hello = "Hello"
// hello and ok are visible here
fmt.Println(hello, ok)
} // block scope ends
================================================
FILE: first/explain/scopes/02-block-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func nope() { // block scope starts
// hello and ok are only visible here
const ok = true
var hello = "Hello"
_ = hello
} // block scope ends
func main() { // block scope starts
// hello and ok are not visible here
// ERROR:
// fmt.Println(hello, ok)
} // block scope ends
================================================
FILE: first/explain/scopes/03-nested-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// I didn't talk about this in a lecture
// As a side-note, I wanted to put it here
// Please review it.
var declareMeAgain = 10
func nested() { // block scope starts
// declares the same variable
// they both can exist together
// this one only belongs to this scope
// package's variable is still intact
var declareMeAgain = 5
fmt.Println("inside nope:", declareMeAgain)
} // block scope ends
func main() { // block scope starts
fmt.Println("inside main:", declareMeAgain)
nested()
// package-level declareMeAgain isn't effected
// from the change inside the nested func
fmt.Println("inside main:", declareMeAgain)
} // block scope ends
================================================
FILE: first/explain/statements/01-execution-flow/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello!")
// Statements change the execution flow
// Especially the control flow statements like `if`
if 5 > 1 {
fmt.Println("bigger")
}
}
================================================
FILE: first/explain/statements/02-semicolons/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello"); fmt.Println("World!")
}
================================================
FILE: first/first/exercises/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE
// Print your name and your best friend's name using
// Println twice
//
// EXPECTED OUTPUT
// YourName
// YourBestFriendName
//
// BONUS
// Use `go run` first.
// And after that use `go build` and run your program.
// ---------------------------------------------------------
func main() {
// ?
// ?
}
================================================
FILE: first/first/exercises/01/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// go run main.go
// go build
// ./solution
func main() {
fmt.Println("Nikola")
fmt.Println("Thomas")
}
================================================
FILE: first/first/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// package main is a special package
// it allows Go to create an executable file
package main
/*
This is a multi-line comment.
import keyword makes another package available
for this .go "file".
import "fmt" lets you access fmt package's functionality
here in this file.
*/
import "fmt"
// "func main" is special.
//
// Go has to know where to start
//
// func main creates a starting point for Go
//
// After compiling the code,
// Go runtime will first run this function
func main() {
// after: import "fmt"
// Println function of "fmt" package becomes available
// Look at what it looks like by typing in the console:
// go doc -src fmt Println
// Println is just an exported function from
// "fmt" package
// Exported = First Letter is uppercase
fmt.Println("Hello Gopher!")
// Go cannot call Println function by itself.
// That's why you need to call it here.
// It only calls `func main` automatically.
// -----
// Go supports Unicode characters in string literals
// And also in source-code: KÖSTEBEK!
// EXERCISE: Remove the comments from below --> //
// fmt.Println("Merhaba Köstebek!")
// Unnecessary note:
// "Merhaba Köstebek" means "Hello Gopher"
// in Turkish language
}
================================================
FILE: first/first/questions/01-code-your-first-program-questions.md
================================================
## What does the package keyword do in the following program?
```go
package main
func main() {
}
```
1. func
2. package *CORRECT*
3. fmt.Println
4. import
> **1:** This keyword is used to declare a new function.
>
>
> **2:** That's right! package keyword allows you to define which package a Go file belongs to.
>
>
> **3:** This is not a keyword. It's the Println function of the fmt package.
>
>
> **4:** This keyword is used to import a package.
>
>
## Which keyword is used to declare a new function?
* func *CORRECT*
* package
* Println
* import
## What is a function?
1. It's like a mini-program. It's a reusable and executable block of code. *CORRECT*
2. It allows Go to execute a program.
3. It allows Go to import a package called function.
4. It prints a message to the console.
> **2:** Go looks for package main and func main to do that. A function doesn't do that on its own.
>
>
> **3:** `import` keyword does that.
>
>
> **4:** For example: `fmt.Println` does that.
>
>
## Do you have to call the main function yourself?
1. Yes, so that, I can execute my program.
2. No, Go calls the main function automatically. *CORRECT*
> **1:** No, you don't need to call the main function. Go automatically executes it.
>
>
## Do you have to call the other functions yourself?
1. Yes, so that, I can execute that function. *CORRECT*
2. Yes, so that, Go can execute my program.
3. No, Go calls the functions automatically.
> **1:** That's right. You need to call a function yourself. Go won't execute it automatically. Go only calls the main function automatically (and some other functions which you didn't learn about yet).
>
>
> **2:** That's only the job of the `func main`. There's only one `func main`.
>
>
> **3:** Go doesn't call any function automatically except the main func (and some other functions which you didn't learn about yet). So, except the main func, you need to call the functions yourself.
>
>
## What does `package main` do?
```go
package main
func main() {
}
```
* It controls everything
* It allows you to properly exit from a program
* It allows you to create an executable Go program *CORRECT*
## What does `func main` do?
```go
package main
func main() {
}
```
1. It contains a package called main
2. Go starts executing your program by using the code inside func main *CORRECT*
3. It prints a message to the console
> **1:** main function doesn't contain a package.
>
>
> **2:** That's right. Go automatically calls the main function to execute your program.
>
>
> **3:** It doesn't print anything at least directly.
>
>
## What does `import "fmt"` do?
```go
package main
import "fmt"
func main() {
fmt.Println("Hi!")
}
```
1. It prints "fmt" to the console
2. It defines a new package called "fmt"
3. It imports the `fmt` package; so you can use its functionalities *CORRECT*
> **1:** `fmt.Println` prints a message not the `import "fmt"`.
>
>
> **2:** `package` keyword does that, not the `import` keyword.
>
>
> **3:** Yes. For example, after you import the fmt package you can call its Println function to print a message to the console.
>
>
## What this program does?
```go
package main
func main() {
}
```
1. It prints a message to the console
2. It's a correct program but it doesn't print anything *CORRECT*
3. It's an incorrect program
> **1:** It doesn't print a message. To do that you can use fmt.Println function.
>
>
> **2:** Yes, it's a correct program but since it doesn't contain fmt.Println it doesn't print anything.
>
>
> **3:** It's a correct program. It uses the package keyword and it has a main function. So, this is a valid and an executable Go program.
>
>
## What does this program print?
```go
package main
func main() {
fmt.Println(Hi! I want to be a Gopher!)
}
```
* Hi! I want to be a Gopher!
* It doesn't print anything
* This program is incorrect *CORRECT*
> **1:** It doesn't pass the message to Println wrapped between double-quotes. It should be like: fmt.Println("Hi! I want to be a Gopher")
>
>
> **3:** It doesn't import "fmt" package. Also see #1.
>
>
## What does this program print?
```go
package main
import "fmt"
func main() {
fmt.Println("Hi there!")
}
```
* Hi there! *CORRECT*
* fmt
* This program is incorrect; it imports the wrong package or there isn't a function called `Println`
> **2:** import "fmt" imports the `fmt` package; so you can use its functionalities.
>
>
> **3:** Actually, this program is correct.
>
>
================================================
FILE: first/first/questions/02-run-your-first-program-questions.md
================================================
## What's the difference between `go build` and `go run`?
1. `go run` just compiles a program; whereas `go build` both compiles and runs it.
2. `go run` both compiles and runs a program; whereas `go build` just compiles it. *CORRECT*
> **1:** It's opposite actually.
>
>
> **2:** `go run` compiles your program and puts it in a temporary directory. Then it runs the compiled program in there.
>
>
## Which one below is true for runtime?
1. It happens when your program starts running on a computer *CORRECT*
2. It happens while your program is being compiled
## Which one below is true for the compile-time?
1. It happens when your program starts running in a computer
2. It happens while your program is being compiled *CORRECT*
## In which stage your program can print a message to the console?
1. While it's being compiled.
2. While it runs (after compile-time). *CORRECT*
3. While it runs (inside the compile-time).
> **1:** In the compilation step your program cannot print a message. In that stage, it's literally dead.
>
>
> **2:** That's right. That's the only time which your program can interact with a computer and instruct it to print a message to the console.
>
>
> **3:** Running can only happen after the compile-time
>
>
================================================
FILE: first/printer/cmd/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Automatically imports!... AWESOME!
import "github.com/inancgumus/learngo/first/printer"
func main() {
printer.Hello()
}
================================================
FILE: first/printer/printer.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package printer
import "fmt"
// Hello is an exported function
func Hello() {
fmt.Println("exported hello")
}
================================================
FILE: first/printer-exercise/solution/golang/cmd/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
// You should replace this with your username
// If you remove this, vs code will do that for you
"github.com/inancgumus/learngo/first/printer-exercise/solution/golang"
)
func main() {
fmt.Println(golang.Version())
}
================================================
FILE: first/printer-exercise/solution/golang/go.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package golang
import (
"runtime"
)
// Version returns the current Go version
func Version() string {
return runtime.Version()
}
================================================
FILE: go.mod
================================================
module github.com/inancgumus/learngo
go 1.13
require (
github.com/fatih/color v1.10.0
github.com/guineveresaenger/golang-rainbow v0.0.0-20171201190047-7b6c54e09b61
github.com/inancgumus/prettyslice v0.0.0-20190305220808-d802ba58098f
github.com/inancgumus/screen v0.0.0-20190314163918-06e984b86ed3
github.com/mattn/go-runewidth v0.0.9
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 // indirect
)
================================================
FILE: go.sum
================================================
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/guineveresaenger/golang-rainbow v0.0.0-20171201190047-7b6c54e09b61 h1:8wAz2sOxcUbqE1haQa0Bg/JoIxq6ihClZSWX2Sni/qc=
github.com/guineveresaenger/golang-rainbow v0.0.0-20171201190047-7b6c54e09b61/go.mod h1:2Myrnv41e4+Cf+NKQs6i9vlZw3EwJd9o8wq1m+A0TaY=
github.com/inancgumus/prettyslice v0.0.0-20190305220808-d802ba58098f h1:Nr2FPhL+zSJ1rer6AjTG4T2rkWIJukiLC9+/RVKVFJE=
github.com/inancgumus/prettyslice v0.0.0-20190305220808-d802ba58098f/go.mod h1:lC0BwLhC6oUR2fTZj1R3+FB5o2lQ0RukM0fKsFhitjw=
github.com/inancgumus/screen v0.0.0-20190314163918-06e984b86ed3 h1:fO9A67/izFYFYky7l1pDP5Dr0BTCRkaQJUG6Jm5ehsk=
github.com/inancgumus/screen v0.0.0-20190314163918-06e984b86ed3/go.mod h1:Ey4uAp+LvIl+s5jRbOHLcZpUDnkjLBROl15fZLwPlTM=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc=
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
================================================
FILE: interfaces/01-methods/book.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type book struct {
title string
price float64
}
func (b book) print() {
// b is a copy of the original `book` value here.
fmt.Printf("%-15s: $%.2f\n", b.title, b.price)
}
// ----------------------------------------------------------------------------
// + you can use the same method names among different types.
// + you don't need to type `printGame`, it's just: `print`.
//
// func (b book) printBook() {
// // b is a copy of the original `book` value here.
// fmt.Printf("%-15s: $%.2f\n", b.title, b.price)
// }
// ----------------------------------------------------------------------------
// b is a copy of the original `book` value here.
//
// func printBook(b book) {
// fmt.Printf("%-15s: $%.2f\n", b.title, b.price)
// }
================================================
FILE: interfaces/01-methods/game.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type game struct {
title string
price float64
}
func (g game) print() {
fmt.Printf("%-15s: $%.2f\n", g.title, g.price)
}
// PREVIOUS CODE:
// ----------------------------------------------------------------------------
// you can use same method name among different types.
// you don't need to type `printGame`, it's just: `print`.
//
// func (g game) printGame() {
// fmt.Printf("%-15s: $%.2f\n", g.title, g.price)
// }
// ----------------------------------------------------------------------------
// you cannot use the same function name within the same package.
//
// func printGame(g game) {
// fmt.Printf("%-15s: $%.2f\n", g.title, g.price)
// }
================================================
FILE: interfaces/01-methods/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
mobydick := book{
title: "moby dick",
price: 10,
}
minecraft := game{
title: "minecraft",
price: 20,
}
tetris := game{
title: "tetris",
price: 5,
}
// #3
mobydick.print() // sends `mobydick` value to `book.print`
minecraft.print() // sends `minecraft` value to `game.print`
tetris.print() // sends `tetris` value to `game.print`
// #2
// mobydick.printBook()
// minecraft.printGame()
// #1
// printBook(mobydick)
// printGame(minecraft)
}
================================================
FILE: interfaces/02-receivers/book.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type book struct {
title string
price float64
}
func (b book) print() {
fmt.Printf("%-15s: $%.2f\n", b.title, b.price)
}
================================================
FILE: interfaces/02-receivers/game.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type game struct {
title string
price float64
}
// be consistent:
// if another method in the same type has a pointer receiver,
// use pointer receivers on the other methods as well.
func (g *game) print() {
fmt.Printf("%-15s: $%.2f\n", g.title, g.price)
}
// + discount gets a copy of `*game`.
// + discount can update the original `game` through the game pointer.
// + it's better to use the same receiver type: `*game` for all methods.
func (g *game) discount(ratio float64) {
g.price *= (1 - ratio)
}
// PREVIOUS CODE:
// + `g` is a copy: `discount` cannot change the original `g`.
// func (g *game) discount(ratio float64) {
// g.price *= (1 - ratio)
// }
================================================
FILE: interfaces/02-receivers/huge.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
type huge struct {
// about ~200mb
games [10_000_000]game
// if this syntax doesn't work on your system, type it as:
// games [10000000]game
}
// only copies a single pointer.
func (h *huge) addr() {
fmt.Printf("%p\n", h)
}
// each time it is called,
// the original value will be copied.
// calling addr() x 10 times = ~2 GB.
// func (h huge) addr() {
// fmt.Printf("%p\n", &h)
// }
================================================
FILE: interfaces/02-receivers/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
var (
mobydick = book{title: "moby dick", price: 10}
minecraft = game{title: "minecraft", price: 20}
tetris = game{title: "tetris", price: 5}
)
// sends a pointer of minecraft to the discount method
// same as: (&minecraft).discount(.1)
minecraft.discount(.1)
mobydick.print()
minecraft.print()
tetris.print()
// creates a variable that occupies 200mb on memory
var h huge
for i := 0; i < 10; i++ {
h.addr()
}
}
================================================
FILE: interfaces/03-nonstructs/book.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type book struct {
title string
price money
}
func (b book) print() {
fmt.Printf("%-15s: %s\n", b.title, b.price.string())
}
================================================
FILE: interfaces/03-nonstructs/game.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type game struct {
title string
price money
}
func (g *game) print() {
fmt.Printf("%-15s: %s\n", g.title, g.price.string())
}
func (g *game) discount(ratio float64) {
g.price *= money(1 - ratio)
}
================================================
FILE: interfaces/03-nonstructs/list.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// + you can attach methods to non-struct types.
// + rule: you need to declare a new type in the same package.
type list []*game
func (l list) print() {
// `list` acts like a `[]game`
if len(l) == 0 {
fmt.Println("Sorry. We're waiting for delivery 🚚.")
return
}
for _, it := range l {
it.print()
}
}
================================================
FILE: interfaces/03-nonstructs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
var (
// mobydick = book{title: "moby dick", price: 10}
minecraft = game{title: "minecraft", price: 20}
tetris = game{title: "tetris", price: 5}
)
var items []*game
items = append(items, &minecraft, &tetris)
// you can attach methods to a compatible type on the fly:
// items -> []*game
// list -> []*game
my := list(items)
// my = nil
// you can call methods even on a nil value
my.print()
}
================================================
FILE: interfaces/03-nonstructs/money.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type money float64
func (m money) string() string {
// $xx.yy
return fmt.Sprintf("$%.2f", m)
}
================================================
FILE: interfaces/04-interfaces/book.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type book struct {
title string
price money
}
func (b book) print() {
fmt.Printf("%-15s: %s\n", b.title, b.price.string())
}
================================================
FILE: interfaces/04-interfaces/game.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type game struct {
title string
price money
}
func (g *game) print() {
fmt.Printf("%-15s: %s\n", g.title, g.price.string())
}
func (g *game) discount(ratio float64) {
g.price *= money(1 - ratio)
}
================================================
FILE: interfaces/04-interfaces/list.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type printer interface {
print()
}
type list []printer
func (l list) print() {
if len(l) == 0 {
fmt.Println("Sorry. We're waiting for delivery 🚚.")
return
}
for _, it := range l {
// fmt.Printf("(%-10T) --> ", it)
it.print()
// you cannot access to the discount method of the game type.
// `it` is a printer not a game.
// it.discount(.5)
}
}
// PREVIOUS CODE:
// type list []*game
// func (l list) print() {
// if len(l) == 0 {
// fmt.Println("Sorry. Our store is closed. We're waiting for the delivery 🚚.")
// return
// }
// for _, it := range l {
// it.print()
// }
// }
================================================
FILE: interfaces/04-interfaces/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
mobydick = book{title: "moby dick", price: 10}
minecraft = game{title: "minecraft", price: 20}
tetris = game{title: "tetris", price: 5}
rubik = puzzle{title: "rubik's cube", price: 5}
)
// thanks to the printer interface we can add different types of values
// to the list.
//
// only rule: they need to implement the `printer` interface.
// to do that: each type needs to have a print method.
var store list
store = append(store, &minecraft, &tetris, mobydick, rubik)
store.print()
// interface values are comparable
fmt.Println(store[0] == &minecraft)
fmt.Println(store[3] == rubik)
}
================================================
FILE: interfaces/04-interfaces/money.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type money float64
func (m money) string() string {
return fmt.Sprintf("$%.2f", m)
}
================================================
FILE: interfaces/04-interfaces/power/blender.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// Blender can be powered
type Blender struct{}
// Draw power to a Blender
func (Blender) Draw(power int) {
fmt.Printf("Blender is drawing %dkW of electrical power.\n", power)
}
================================================
FILE: interfaces/04-interfaces/power/kettle.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// Kettle can be powered
type Kettle struct{}
// Draw power to a Kettle
func (Kettle) Draw(power int) {
fmt.Printf("Kettle is drawing %dkW of electrical power.\n", power)
}
================================================
FILE: interfaces/04-interfaces/power/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"time"
)
// RUN IT WITH ALL THE FILES IN THE DIRECTORY LIKE SO:
// go run .
func main() {
rand.Seed(time.Now().UnixNano())
var (
blender Blender
player Player
kettle Kettle
mixer Mixer
)
socket := &Socket{100}
fmt.Printf("Socket's available power is %d kW.\n", socket.power)
if err := socket.Plug(blender); err != nil {
fmt.Println("Blender cannot be powered up:", err)
}
if err := socket.Plug(player); err != nil {
fmt.Println("Player cannot be powered up:", err)
}
if err := socket.Plug(kettle); err != nil {
fmt.Println("Kettle cannot be powered up:", err)
}
if err := socket.Plug(mixer); err != nil {
fmt.Println("Mixer cannot be powered up:", err)
}
fmt.Printf("Socket's available power is %d kW.\n", socket.power)
}
================================================
FILE: interfaces/04-interfaces/power/mixer.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// Mixer can be powered
type Mixer struct{}
// Draw power to a Mixer
func (Mixer) Draw(power int) {
fmt.Printf("Mixer is drawing %dkW of electrical power.\n", power)
}
================================================
FILE: interfaces/04-interfaces/power/player.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
// Player can be powered
type Player struct{}
// Draw power to a Player
func (Player) Draw(power int) {
fmt.Printf("Player is drawing %dkW of electrical power.\n", power)
}
================================================
FILE: interfaces/04-interfaces/power/socket.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
)
// PowerDrawer represents an electrical device that can draw power.
// The power source doesn't have to be a Socket.
type PowerDrawer interface {
Draw(power int)
}
// Socket has the power!
type Socket struct {
power int
}
// Plug a device to draw power from the `Socket`
func (s *Socket) Plug(device PowerDrawer) error {
n := rand.Intn(50) + 1
if s.power-n < 0 {
return fmt.Errorf("socket is out of power for %dkW", n)
}
s.power -= n
device.Draw(n)
return nil
}
================================================
FILE: interfaces/04-interfaces/puzzle.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type puzzle struct {
title string
price money
}
// if you remove this method,
// you can no longer add it to the `store` in `main()`.
func (p puzzle) print() {
fmt.Printf("%-15s: %s\n", p.title, p.price.string())
}
================================================
FILE: interfaces/05-type-assertion/book.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type book struct {
title string
price money
}
func (b book) print() {
fmt.Printf("%-15s: %s\n", b.title, b.price.string())
}
================================================
FILE: interfaces/05-type-assertion/game.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type game struct {
title string
price money
}
func (g *game) print() {
fmt.Printf("%-15s: %s\n", g.title, g.price.string())
}
func (g *game) discount(ratio float64) {
g.price *= money(1 - ratio)
}
================================================
FILE: interfaces/05-type-assertion/list.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type printer interface {
print()
// use type assertion when you cannot change the interface.
// discount(ratio float64)
}
type list []printer
func (l list) print() {
if len(l) == 0 {
fmt.Println("Sorry. We're waiting for delivery 🚚.")
return
}
for _, it := range l {
it.print()
}
}
// type assertion can extract the wrapped value.
// or: it can put the value into another interface.
func (l list) discount(ratio float64) {
// you can declare an interface in a function/method as well.
// interface is just a type.
type discounter interface {
discount(float64)
}
for _, it := range l {
// you can assert to an interface.
// and extract another interface.
if it, ok := it.(discounter); ok {
it.discount(ratio)
}
}
}
// ----
// func (l list) discount(ratio float64) {
// for _, it := range l {
// // you can inline-assert interfaces
// // interface is just a type.
// g, ok := it.(interface{ discount(float64) })
// if !ok {
// continue
// }
// g.discount(ratio)
// }
// }
// ----
// // type assertion can pull out the real value behind an interface value.
// // it can also check whether the value convertable to a given type.
// func (l list) discount(ratio float64) {
// for _, it := range l {
// g, ok := it.(*game)
// if !ok {
// continue
// }
// g.discount(ratio)
// }
// }
================================================
FILE: interfaces/05-type-assertion/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
var (
mobydick = book{title: "moby dick", price: 10}
minecraft = game{title: "minecraft", price: 20}
tetris = game{title: "tetris", price: 5}
rubik = puzzle{title: "rubik's cube", price: 5}
yoda = toy{title: "yoda", price: 150}
)
var store list
store = append(store, &minecraft, &tetris, mobydick, rubik, &yoda)
// #2
store.discount(.5)
store.print()
// #1
// var p printer
// p = &tetris
// tetris.discount(.5)
// p.print()
}
================================================
FILE: interfaces/05-type-assertion/money.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type money float64
func (m money) string() string {
return fmt.Sprintf("$%.2f", m)
}
================================================
FILE: interfaces/05-type-assertion/puzzle.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type puzzle struct {
title string
price money
}
func (p puzzle) print() {
fmt.Printf("%-15s: %s\n", p.title, p.price.string())
}
================================================
FILE: interfaces/05-type-assertion/toy.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type toy struct {
title string
price money
}
func (t *toy) print() {
fmt.Printf("%-15s: %s\n", t.title, t.price.string())
}
func (t *toy) discount(ratio float64) {
t.price *= money(1 - ratio)
}
================================================
FILE: interfaces/06-empty-interface/book.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"time"
)
type book struct {
title string
price money
published interface{}
}
func (b book) print() {
p := format(b.published)
fmt.Printf("%-15s: %s - (%v)\n", b.title, b.price.string(), p)
}
func format(v interface{}) string {
// book{title: "hobbit", price: 25},
if v == nil {
return "unknown"
}
var t int
// book{title: "moby dick", price: 10, published: 118281600},
if v, ok := v.(int); ok {
t = v
}
// book{title: "odyssey", price: 15, published: "733622400"},
if v, ok := v.(string); ok {
t, _ = strconv.Atoi(v)
}
u := time.Unix(int64(t), 0)
return u.String()
}
================================================
FILE: interfaces/06-empty-interface/empty/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// Let's create a variable using the empty interface type.
var any interface{}
// The variable can accept any type of value.
any = []int{1, 2, 3}
any = map[int]bool{1: true, 2: false}
any = "hello"
any = 3
// You can't multiply the last number.
// Reason: `any` is an `interface{}`, it's not a number.
// any = any * 2
// any = int(any) * 2
any = any.(int) * 2
fmt.Println(any)
}
================================================
FILE: interfaces/06-empty-interface/empty2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
nums := []int{1, 2, 3}
// Store a slice in `any`
var any interface{}
any = nums
// `any` is an empty interface value, it's not a slice.
// You cannot get its length. It has no length.
// _ = len(any)
// When you extract the slice from it, you can get the slice's length.
_ = len(any.([]int))
// You cannot assign an `[]T` slice to `[]interface{}` slice.
// Where `T` can be of any type.
// Reason: `[]interface{}` is a slice, it's not an `empty interface` value.
var many []interface{}
// many = nums
// The same reason that you can't assign an `[]int` to a `[]string`.
// var words []string = nums
// You need to copy the elements from `nums` to `many` manually.
for _, n := range nums {
many = append(many, n)
}
fmt.Println(many)
// Each element of the `many` slice is an `empty interface` value.
// el := many[0]
}
================================================
FILE: interfaces/06-empty-interface/game.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type game struct {
title string
price money
}
func (g *game) print() {
fmt.Printf("%-15s: %s\n", g.title, g.price.string())
}
func (g *game) discount(ratio float64) {
g.price *= money(1 - ratio)
}
================================================
FILE: interfaces/06-empty-interface/list.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type printer interface {
print()
}
type list []printer
func (l list) print() {
if len(l) == 0 {
fmt.Println("Sorry. We're waiting for delivery 🚚.")
return
}
for _, it := range l {
it.print()
}
}
func (l list) discount(ratio float64) {
type discounter interface {
discount(float64)
}
for _, it := range l {
if it, ok := it.(discounter); ok {
it.discount(ratio)
}
}
}
================================================
FILE: interfaces/06-empty-interface/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
store := list{
book{title: "moby dick", price: 10, published: 118281600},
book{title: "odyssey", price: 15, published: "733622400"},
book{title: "hobbit", price: 25},
puzzle{title: "rubik's cube", price: 5},
&game{title: "minecraft", price: 20},
&game{title: "tetris", price: 5},
&toy{title: "yoda", price: 150},
}
store.discount(.5)
store.print()
}
================================================
FILE: interfaces/06-empty-interface/money.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type money float64
func (m money) string() string {
return fmt.Sprintf("$%.2f", m)
}
================================================
FILE: interfaces/06-empty-interface/puzzle.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type puzzle struct {
title string
price money
}
func (p puzzle) print() {
fmt.Printf("%-15s: %s\n", p.title, p.price.string())
}
================================================
FILE: interfaces/06-empty-interface/toy.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type toy struct {
title string
price money
}
func (t *toy) print() {
fmt.Printf("%-15s: %s\n", t.title, t.price.string())
}
func (t *toy) discount(ratio float64) {
t.price *= money(1 - ratio)
}
================================================
FILE: interfaces/07-type-switch/book.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"time"
)
type book struct {
title string
price money
published interface{}
}
func (b book) print() {
p := format(b.published)
fmt.Printf("%-15s: %s - (%v)\n", b.title, b.price.string(), p)
}
func format(v interface{}) string {
var t int
switch v := v.(type) {
case int:
// book{title: "moby dick", price: 10, published: 118281600},
t = v
case string:
// book{title: "odyssey", price: 15, published: "733622400"},
t, _ = strconv.Atoi(v)
default:
// book{title: "hobbit", price: 25},
return "unknown"
}
// Mon Jan 2 15:04:05 -0700 MST 2006
const layout = "2006/01"
u := time.Unix(int64(t), 0)
return u.Format(layout)
}
================================================
FILE: interfaces/07-type-switch/game.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type game struct {
title string
price money
}
func (g *game) print() {
fmt.Printf("%-15s: %s\n", g.title, g.price.string())
}
func (g *game) discount(ratio float64) {
g.price *= money(1 - ratio)
}
================================================
FILE: interfaces/07-type-switch/list.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type printer interface {
print()
}
type list []printer
func (l list) print() {
if len(l) == 0 {
fmt.Println("Sorry. We're waiting for delivery 🚚.")
return
}
for _, it := range l {
it.print()
}
}
func (l list) discount(ratio float64) {
type discounter interface {
discount(float64)
}
for _, it := range l {
if it, ok := it.(discounter); ok {
it.discount(ratio)
}
}
}
================================================
FILE: interfaces/07-type-switch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
store := list{
book{title: "moby dick", price: 10, published: 118281600},
book{title: "odyssey", price: 15, published: "733622400"},
book{title: "hobbit", price: 25},
puzzle{title: "rubik's cube", price: 5},
&game{title: "minecraft", price: 20},
&game{title: "tetris", price: 5},
&toy{title: "yoda", price: 150},
}
store.discount(.5)
store.print()
}
================================================
FILE: interfaces/07-type-switch/money.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type money float64
func (m money) string() string {
return fmt.Sprintf("$%.2f", m)
}
================================================
FILE: interfaces/07-type-switch/puzzle.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type puzzle struct {
title string
price money
}
func (p puzzle) print() {
fmt.Printf("%-15s: %s\n", p.title, p.price.string())
}
================================================
FILE: interfaces/07-type-switch/toy.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type toy struct {
title string
price money
}
func (t *toy) print() {
fmt.Printf("%-15s: %s\n", t.title, t.price.string())
}
func (t *toy) discount(ratio float64) {
t.price *= money(1 - ratio)
}
================================================
FILE: interfaces/08-promoted-methods/book.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"time"
)
type book struct {
// embed the product type into the book type.
// all the fields and methods of the product will be
// available in this book type.
product
published interface{}
}
// book type's print method takes priority.
//
// + when you call it on a book value, the following method will
// be executed.
//
// + if it wasn't here, the product type's print method would
// have been executed.
func (b *book) print() {
// the book can also call the embedded product's print method
// if it wants to, as in here:
b.product.print()
p := format(b.published)
fmt.Printf("\t - (%v)\n", p)
}
func format(v interface{}) string {
var t int
switch v := v.(type) {
case int:
// book{title: "moby dick", price: 10, published: 118281600},
t = v
case string:
// book{title: "odyssey", price: 15, published: "733622400"},
t, _ = strconv.Atoi(v)
default:
// book{title: "hobbit", price: 25},
return "unknown"
}
// Mon Jan 2 15:04:05 -0700 MST 2006
const layout = "2006/01"
u := time.Unix(int64(t), 0)
return u.Format(layout)
}
================================================
FILE: interfaces/08-promoted-methods/game.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type game struct {
product
}
================================================
FILE: interfaces/08-promoted-methods/list.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type item interface {
print()
discount(ratio float64)
}
type list []item
func (l list) print() {
if len(l) == 0 {
fmt.Println("Sorry. We're waiting for delivery 🚚.")
return
}
for _, it := range l {
it.print()
}
}
func (l list) discount(ratio float64) {
for _, it := range l {
it.discount(ratio)
}
}
================================================
FILE: interfaces/08-promoted-methods/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
store := list{
&book{product{"moby dick", 10}, 118281600},
&book{product{"odyssey", 15}, "733622400"},
&book{product{"hobbit", 25}, nil},
&puzzle{product{"rubik's cube", 5}},
&game{product{"minecraft", 20}},
&game{product{"tetris", 5}},
&toy{product{"yoda", 150}},
}
store.discount(.5)
store.print()
// t := &toy{product{"yoda", 150}}
// fmt.Printf("%#v\n", t)
// b := &book{product{"moby dick", 10}, 118281600}
// fmt.Printf("%#v\n", b)
}
================================================
FILE: interfaces/08-promoted-methods/money.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type money float64
func (m money) string() string {
return fmt.Sprintf("$%.2f", m)
}
================================================
FILE: interfaces/08-promoted-methods/product.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type product struct {
title string
price money
}
func (p *product) print() {
fmt.Printf("%-15s: %s\n", p.title, p.price.string())
}
func (p *product) discount(ratio float64) {
p.price *= money(1 - ratio)
}
================================================
FILE: interfaces/08-promoted-methods/puzzle.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type puzzle struct {
product
}
================================================
FILE: interfaces/08-promoted-methods/toy.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type toy struct {
product
}
================================================
FILE: interfaces/09-little-refactor/list.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type list []*product
func (l list) print() {
if len(l) == 0 {
fmt.Println("Sorry. We're waiting for delivery 🚚.")
return
}
for _, p := range l {
p.print()
}
}
func (l list) discount(ratio float64) {
for _, p := range l {
p.discount(ratio)
}
}
================================================
FILE: interfaces/09-little-refactor/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
l := list{
{title: "moby dick", price: 10, released: toTimestamp(118281600)},
{title: "odyssey", price: 15, released: toTimestamp("733622400")},
{title: "hobbit", price: 25},
}
l.discount(.5)
l.print()
}
/*
Summary:
- Prefer to work directly with concrete types
- Leads to a simple and easy to understand code
- Abstractions (interfaces) can unnecessarily complicate your code
- Separating responsibilities is critical
- Timestamp type can represent, store, and print a UNIX timestamp
- When a type anonymously embeds a type, it can use the methods of the embedded type as its own.
- Timestamp embeds a time.Time
- So you can call the methods of the time.Time through a timestamp value
*/
================================================
FILE: interfaces/09-little-refactor/money.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type money float64
func (m money) string() string {
return fmt.Sprintf("$%.2f", m)
}
================================================
FILE: interfaces/09-little-refactor/product.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
type product struct {
title string
price money
released timestamp
}
func (p *product) print() {
fmt.Printf("%s: %s (%s)\n", p.title, p.price.string(), p.released.string())
}
func (p *product) discount(ratio float64) {
p.price *= money(1 - ratio)
}
================================================
FILE: interfaces/09-little-refactor/timestamp.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"strconv"
"time"
)
// timestamp stores, formats and automatically prints a timestamp.
type timestamp struct {
// timestamp anonymously embeds a time.
// no need to convert a time value to a timestamp value to use the methods of the time type.
time.Time
}
func (ts timestamp) string() string {
if ts.IsZero() { // same as: ts.Time.IsZero()
return "unknown"
}
// Mon Jan 2 15:04:05 -0700 MST 2006
const layout = "2006/01"
return ts.Format(layout) // same as: ts.Time.Format(layout)
}
// toTimestamp returns a timestamp value depending on the type of `v`.
func toTimestamp(v interface{}) (ts timestamp) {
var t int
switch v := v.(type) {
case int:
t = v
case string:
t, _ = strconv.Atoi(v)
}
ts.Time = time.Unix(int64(t), 0)
return ts
}
================================================
FILE: interfaces/10-stringer/_handlemethods.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// In the depths of the Go standard library's fmt package...
// Printing functions use the handleMethods method.
// Example:
// var pocket money = 10
// fmt.Println(pocket)
// the argument can be any type of value
// stores the pocket variable in the argument variable
// ^
// |
func (p *pp) handleMethods(argument interface{}) (handled bool) {
// ...
// Checks whether a given argument is an error or an fmt.Stringer
switch v := argument.(type) {
// ...
// If the argument is a Stringer, calls its String() method
case Stringer:
// ...
// pocket.String()
// ^
// |
p.fmtString(v.String(), verb)
return
}
// ...
}
/*
The original `handleMethods` code is more involved:
https://github.com/golang/go/blob/6f51082da77a1d4cafd5b7af0db69293943f4066/src/fmt/print.go#L574
-> 574#handleMethods(..)
-> 627#Stringer type check: If `v` is a Stringer, run:
-> 630#v.String()
*/
================================================
FILE: interfaces/10-stringer/list.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"strings"
)
type list []*product
func (l list) String() string {
if len(l) == 0 {
return "Sorry. We're waiting for delivery 🚚.\n"
}
var str strings.Builder
for _, p := range l {
// fmt.Printf("* %s\n", p)
str.WriteString("* ")
str.WriteString(p.String())
str.WriteRune('\n')
}
return str.String()
}
func (l list) discount(ratio float64) {
for _, p := range l {
p.discount(ratio)
}
}
================================================
FILE: interfaces/10-stringer/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
l := list{
{title: "moby dick", price: 10, released: toTimestamp(118281600)},
{title: "odyssey", price: 15, released: toTimestamp("733622400")},
{title: "hobbit", price: 25},
}
l.discount(.5)
// The list is a stringer.
// The `fmt.Print` function can print the `l`
// by calling `l`'s `String()` method.
//
// Underneath, `fmt.Print` uses a type switch to
// detect whether a type is a Stringer:
// https://golang.org/src/fmt/print.go#L627
fmt.Print(l)
// The money type is a stringer.
// You don't need to call the String method when printing a value of it.
// var pocket money = 10
// fmt.Println("I have", pocket)
}
/*
Summary:
- fmt.Stringer has one method: String()
- That returns a string.
- It is better to be an fmt.Stringer instead of printing directly.
- Implement the String() on a type and the type can represent itself as a string.
- Bonus: The functions in the fmt package can print your type.
- They use type assertion to detect if a type implements a String() method.
- strings.Builder can efficiently combine multiple string values.
*/
================================================
FILE: interfaces/10-stringer/money.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type money float64
// String() returns a string representation of money.
// money is an fmt.Stringer.
func (m money) String() string {
return fmt.Sprintf("$%.2f", m)
}
================================================
FILE: interfaces/10-stringer/product.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
type product struct {
title string
price money
released timestamp
}
func (p *product) String() string {
return fmt.Sprintf("%s: %s (%s)", p.title, p.price, p.released)
}
func (p *product) discount(ratio float64) {
p.price *= money(1 - ratio)
}
================================================
FILE: interfaces/10-stringer/timestamp.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"strconv"
"time"
)
// timestamp stores, formats and automatically prints a timestamp.
type timestamp struct {
// timestamp anonymously embeds a time.
// no need to convert a time value to a timestamp value to use the methods of the time type.
time.Time
}
// String() returns a string representation of timestamp.
// timestamp is an fmt.Stringer.
func (ts timestamp) String() string {
if ts.IsZero() { // same as: ts.Time.IsZero()
return "unknown"
}
// Mon Jan 2 15:04:05 -0700 MST 2006
const layout = "2006/01"
return ts.Format(layout) // same as: ts.Time.Format(layout)
}
// toTimestamp returns a timestamp value depending on the type of `v`.
func toTimestamp(v interface{}) (ts timestamp) {
var t int
switch v := v.(type) {
case int:
t = v
case string:
t, _ = strconv.Atoi(v)
}
ts.Time = time.Unix(int64(t), 0)
return ts
}
================================================
FILE: interfaces/11-sort/list.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"sort"
"strings"
)
// product is now *product because sorting will unnecessarily copy the product values
type list []*product
func (l list) String() string {
if len(l) == 0 {
return "Sorry. We're waiting for delivery 🚚.\n"
}
var str strings.Builder
for _, p := range l {
// fmt.Printf("* %s\n", p)
str.WriteString("* ")
str.WriteString(p.String())
str.WriteRune('\n')
}
return str.String()
}
func (l list) discount(ratio float64) {
for _, p := range l {
p.discount(ratio)
}
}
// implementation of the sort.Interface:
// by default `list` sorts by `title`.
func (l list) Len() int { return len(l) }
func (l list) Less(i, j int) bool { return l[i].title < l[j].title }
func (l list) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
// byRelease sorts by product release dates.
type byRelease struct {
// byRelease embeds `list` and reuses list's Len and Swap methods.
list
}
// Less takes priority over the Less method of the `list`.
// `sort.Sort` will first call this method instead of the `list`'s Less method.
func (br byRelease) Less(i, j int) bool {
// `Before()` accepts a `time.Time` but `released` is not `time.Time`.
return br.list[i].released.Before(br.list[j].released.Time)
}
/*
Anonymous embedding means auto-forwarding method calls to the embedded value:
func (br byRelease) Len() int { return br.list.Len() }
func (br byRelease) Swap(i, j int) { br.list.Swap(i, j) }
*/
func byReleaseDate(l list) sort.Interface {
return &byRelease{l}
}
================================================
FILE: interfaces/11-sort/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"sort"
)
func main() {
l := list{
{title: "moby dick", price: 10, released: toTimestamp(118281600)},
{title: "odyssey", price: 15, released: toTimestamp("733622400")},
{title: "hobbit", price: 25},
}
// sort.Sort(l)
// sort.Sort(sort.Reverse(l))
// sort.Sort(byReleaseDate(l))
sort.Sort(sort.Reverse(byReleaseDate(l)))
fmt.Print(l)
}
/*
Summary:
- sort.Sort() can sort any type that implements the sort.Interface
- sort.Interface has three methods: Len(), Less(), Swap()
- Len() returns the length of a collection.
- Less(i, j) should return true when an element comes before another one.
- Swap(i, j)s the elements when Less() returns true.
- sort.Reverse() can reverse sort a type that satisfies the sort.Interface.
- You can customize the sorting:
- Either by implementing the sort.Interface methods,
- or by anonymously embedding a type that already satisfies the sort.Interface
- and adding a Less() method.
- Anonymous embedding means auto-forwarding method calls to an embedded value.
*/
================================================
FILE: interfaces/11-sort/money.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type money float64
func (m money) String() string {
return fmt.Sprintf("$%.2f", m)
}
================================================
FILE: interfaces/11-sort/product.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
type product struct {
title string
price money
released timestamp
}
func (p *product) String() string {
return fmt.Sprintf("%s: %s (%s)", p.title, p.price, p.released)
}
func (p *product) discount(ratio float64) {
p.price *= money(1 - ratio)
}
================================================
FILE: interfaces/11-sort/timestamp.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"strconv"
"time"
)
type timestamp struct {
time.Time
}
func (ts timestamp) String() string {
if ts.IsZero() {
return "unknown"
}
// Mon Jan 2 15:04:05 -0700 MST 2006
const layout = "2006/01"
return ts.Format(layout)
}
func toTimestamp(v interface{}) (ts timestamp) {
var t int
switch v := v.(type) {
case int:
t = v
case string:
t, _ = strconv.Atoi(v)
}
ts.Time = time.Unix(int64(t), 0)
return ts
}
================================================
FILE: interfaces/12-marshaler/database.json
================================================
[
{
"title": "moby dick",
"price": 10,
"released": 118281600
},
{
"title": "odyssey",
"price": 15,
"released": 733622400
},
{
"title": "hobbit",
"price": 25,
"released": -62135596800
}
]
================================================
FILE: interfaces/12-marshaler/list.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"sort"
"strings"
)
type list []*product
func (l list) String() string {
if len(l) == 0 {
return "Sorry. We're waiting for delivery 🚚.\n"
}
var str strings.Builder
for _, p := range l {
// fmt.Printf("* %s\n", p)
str.WriteString("* ")
str.WriteString(p.String())
str.WriteRune('\n')
}
return str.String()
}
func (l list) discount(ratio float64) {
for _, p := range l {
p.discount(ratio)
}
}
// implementation of the sort.Interface:
// by default `list` sorts by `Title`.
func (l list) Len() int { return len(l) }
func (l list) Less(i, j int) bool { return l[i].Title < l[j].Title }
func (l list) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
// byRelease sorts by product release dates.
type byRelease struct{ list }
func (br byRelease) Less(i, j int) bool {
return br.list[i].Released.Before(br.list[j].Released.Time)
}
func byReleaseDate(l list) sort.Interface {
return &byRelease{l}
}
================================================
FILE: interfaces/12-marshaler/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"encoding/json"
"fmt"
"log"
)
const data = `[
{
"title": "moby dick",
"price": 10,
"released": 118281600
},
{
"title": "odyssey",
"price": 15,
"released": 733622400
},
{
"title": "hobbit",
"price": 25,
"released": -62135596800
}
]`
func main() {
/* encoding */
l := list{
{Title: "moby dick", Price: 10, Released: toTimestamp(118281600)},
{Title: "odyssey", Price: 15, Released: toTimestamp("733622400")},
{Title: "hobbit", Price: 25},
}
data, err := json.MarshalIndent(l, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
/* decoding */
// var l list
// if err := json.Unmarshal([]byte(data), &l); err != nil {
// log.Fatal(err)
// }
// fmt.Print(l)
}
/*
Summary:
- json.Marshal() and json.MarshalIndent() can only encode primitive types.
- Custom types can tell the encoder how to encode.
- To do that satisfy the json.Marshaler interface.
- json.Unmarshal() can only decode primitive types.
- Custom types can tell the decoder how to decode.
- To do that satisfy the json.Unmarshaler interface.
- strconv.AppendInt() can append an int value to a []byte.
- There are several other functions in the strconv package for other primitive types as well.
- Do not make unnecessary string <-> []byte conversions.
- log.Fatal() can print the given error message and terminate the program.
- Use it only from the main(). Do not use it in other functions.
- main() is should be the main driver of a program.
*/
================================================
FILE: interfaces/12-marshaler/money.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
type money float64
func (m money) String() string {
return fmt.Sprintf("$%.2f", m)
}
================================================
FILE: interfaces/12-marshaler/product.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
type product struct {
Title string `json:"title"`
Price money `json:"price"`
Released timestamp `json:"released"`
}
func (p *product) String() string {
return fmt.Sprintf("%s: %s (%s)", p.Title, p.Price, p.Released)
}
func (p *product) discount(ratio float64) {
p.Price *= money(1 - ratio)
}
================================================
FILE: interfaces/12-marshaler/timestamp.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"strconv"
"time"
)
type timestamp struct {
time.Time
}
// implementation of the fmt.Stringer interface:
func (ts timestamp) String() string {
if ts.IsZero() {
return "unknown"
}
// Mon Jan 2 15:04:05 -0700 MST 2006
const layout = "2006/01"
return ts.Format(layout)
}
// implementation of the json.Marshaler and json.Unmarshaler interfaces:
// timestamp knows how to decode itself from json.
// json.Unmarshal and json.Decode call this method.
func (ts *timestamp) UnmarshalJSON(data []byte) error {
*ts = toTimestamp(string(data))
return nil
}
// timestamp knows how to encode itself to json.
// json.Marshal and json.Encode call this method.
func (ts timestamp) MarshalJSON() (data []byte, _ error) {
return strconv.AppendInt(data, ts.Unix(), 10), nil
}
func toTimestamp(v interface{}) (ts timestamp) {
var t int
switch v := v.(type) {
case int:
t = v
case string:
t, _ = strconv.Atoi(v)
}
ts.Time = time.Unix(int64(t), 0)
return ts
}
================================================
FILE: interfaces/13-io/alice.txt
================================================
ALICE'S ADVENTURES IN WONDERLAND
Lewis Carroll
CHAPTER I
Down the Rabbit-Hole
Alice was beginning to get very tired of sitting by her sister
on the bank, and of having nothing to do: once or twice she had
peeped into the book her sister was reading, but it had no
pictures or conversations in it, `and what is the use of a book,'
thought Alice `without pictures or conversation?'
So she was considering in her own mind (as well as she could,
for the hot day made her feel very sleepy and stupid), whether
the pleasure of making a daisy-chain would be worth the trouble
of getting up and picking the daisies, when suddenly a White
Rabbit with pink eyes ran close by her.
There was nothing so VERY remarkable in that; nor did Alice
think it so VERY much out of the way to hear the Rabbit say to
itself, `Oh dear! Oh dear! I shall be late!' (when she thought
it over afterwards, it occurred to her that she ought to have
wondered at this, but at the time it all seemed quite natural);
but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT-
POCKET, and looked at it, and then hurried on, Alice started to
her feet, for it flashed across her mind that she had never
before seen a rabbit with either a waistcoat-pocket, or a watch to
take out of it, and burning with curiosity, she ran across the
field after it, and fortunately was just in time to see it pop
down a large rabbit-hole under the hedge.
In another moment down went Alice after it, never once
considering how in the world she was to get out again.
The rabbit-hole went straight on like a tunnel for some way,
and then dipped suddenly down, so suddenly that Alice had not a
moment to think about stopping herself before she found herself
falling down a very deep well.
Either the well was very deep, or she fell very slowly, for she
had plenty of time as she went down to look about her and to
wonder what was going to happen next. First, she tried to look
down and make out what she was coming to, but it was too dark to
see anything; then she looked at the sides of the well, and
noticed that they were filled with cupboards and book-shelves;
here and there she saw maps and pictures hung upon pegs. She
took down a jar from one of the shelves as she passed; it was
labelled `ORANGE MARMALADE', but to her great disappointment it
was empty: she did not like to drop the jar for fear of killing
somebody, so managed to put it into one of the cupboards as she
fell past it.
`Well!' thought Alice to herself, `after such a fall as this, I
shall think nothing of tumbling down stairs! How brave they'll
all think me at home! Why, I wouldn't say anything about it,
even if I fell off the top of the house!' (Which was very likely
true.)
Down, down, down. Would the fall NEVER come to an end! `I
wonder how many miles I've fallen by this time?' she said aloud.
`I must be getting somewhere near the centre of the earth. Let
me see: that would be four thousand miles down, I think--' (for,
you see, Alice had learnt several things of this sort in her
lessons in the schoolroom, and though this was not a VERY good
opportunity for showing off her knowledge, as there was no one to
listen to her, still it was good practice to say it over) `--yes,
that's about the right distance--but then I wonder what Latitude
or Longitude I've got to?' (Alice had no idea what Latitude was,
or Longitude either, but thought they were nice grand words to
say.)
Presently she began again. `I wonder if I shall fall right
THROUGH the earth! How funny it'll seem to come out among the
people that walk with their heads downward! The Antipathies, I
think--' (she was rather glad there WAS no one listening, this
time, as it didn't sound at all the right word) `--but I shall
have to ask them what the name of the country is, you know.
Please, Ma'am, is this New Zealand or Australia?' (and she tried
to curtsey as she spoke--fancy CURTSEYING as you're falling
through the air! Do you think you could manage it?) `And what
an ignorant little girl she'll think me for asking! No, it'll
never do to ask: perhaps I shall see it written up somewhere.'
Down, down, down. There was nothing else to do, so Alice soon
began talking again. `Dinah'll miss me very much to-night, I
should think!' (Dinah was the cat.) `I hope they'll remember
her saucer of milk at tea-time. Dinah my dear! I wish you were
down here with me! There are no mice in the air, I'm afraid, but
you might catch a bat, and that's very like a mouse, you know.
But do cats eat bats, I wonder?' And here Alice began to get
rather sleepy, and went on saying to herself, in a dreamy sort of
way, `Do cats eat bats? Do cats eat bats?' and sometimes, `Do
bats eat cats?' for, you see, as she couldn't answer either
question, it didn't much matter which way she put it. She felt
that she was dozing off, and had just begun to dream that she
was walking hand in hand with Dinah, and saying to her very
earnestly, `Now, Dinah, tell me the truth: did you ever eat a
bat?' when suddenly, thump! thump! down she came upon a heap of
sticks and dry leaves, and the fall was over.
Alice was not a bit hurt, and she jumped up on to her feet in a
moment: she looked up, but it was all dark overhead; before her
was another long passage, and the White Rabbit was still in
sight, hurrying down it. There was not a moment to be lost:
away went Alice like the wind, and was just in time to hear it
say, as it turned a corner, `Oh my ears and whiskers, how late
it's getting!' She was close behind it when she turned the
corner, but the Rabbit was no longer to be seen: she found
herself in a long, low hall, which was lit up by a row of lamps
hanging from the roof.
There were doors all round the hall, but they were all locked;
and when Alice had been all the way down one side and up the
other, trying every door, she walked sadly down the middle,
wondering how she was ever to get out again.
Suddenly she came upon a little three-legged table, all made of
solid glass; there was nothing on it except a tiny golden key,
and Alice's first thought was that it might belong to one of the
doors of the hall; but, alas! either the locks were too large, or
the key was too small, but at any rate it would not open any of
them. However, on the second time round, she came upon a low
curtain she had not noticed before, and behind it was a little
door about fifteen inches high: she tried the little golden key
in the lock, and to her great delight it fitted!
Alice opened the door and found that it led into a small
passage, not much larger than a rat-hole: she knelt down and
looked along the passage into the loveliest garden you ever saw.
How she longed to get out of that dark hall, and wander about
among those beds of bright flowers and those cool fountains, but
she could not even get her head though the doorway; `and even if
my head would go through,' thought poor Alice, `it would be of
very little use without my shoulders. Oh, how I wish
I could shut up like a telescope! I think I could, if I only
know how to begin.' For, you see, so many out-of-the-way things
had happened lately, that Alice had begun to think that very few
things indeed were really impossible.
There seemed to be no use in waiting by the little door, so she
went back to the table, half hoping she might find another key on
it, or at any rate a book of rules for shutting people up like
telescopes: this time she found a little bottle on it, (`which
certainly was not here before,' said Alice,) and round the neck
of the bottle was a paper label, with the words `DRINK ME'
beautifully printed on it in large letters.
It was all very well to say `Drink me,' but the wise little
Alice was not going to do THAT in a hurry. `No, I'll look
first,' she said, `and see whether it's marked "poison" or not';
for she had read several nice little histories about children who
had got burnt, and eaten up by wild beasts and other unpleasant
things, all because they WOULD not remember the simple rules
their friends had taught them: such as, that a red-hot poker
will burn you if you hold it too long; and that if you cut your
finger VERY deeply with a knife, it usually bleeds; and she had
never forgotten that, if you drink much from a bottle marked
`poison,' it is almost certain to disagree with you, sooner or
later.
However, this bottle was NOT marked `poison,' so Alice ventured
to taste it, and finding it very nice, (it had, in fact, a sort
of mixed flavour of cherry-tart, custard, pine-apple, roast
turkey, toffee, and hot buttered toast,) she very soon finished
it off.
* * * * * * *
* * * * * *
* * * * * * *
`What a curious feeling!' said Alice; `I must be shutting up
like a telescope.'
And so it was indeed: she was now only ten inches high, and
her face brightened up at the thought that she was now the right
size for going though the little door into that lovely garden.
First, however, she waited for a few minutes to see if she was
going to shrink any further: she felt a little nervous about
this; `for it might end, you know,' said Alice to herself, `in my
going out altogether, like a candle. I wonder what I should be
like then?' And she tried to fancy what the flame of a candle is
like after the candle is blown out, for she could not remember
ever having seen such a thing.
After a while, finding that nothing more happened, she decided
on going into the garden at once; but, alas for poor Alice! when
she got to the door, she found he had forgotten the little golden
key, and when she went back to the table for it, she found she
could not possibly reach it: she could see it quite plainly
through the glass, and she tried her best to climb up one of the
legs of the table, but it was too slippery; and when she had
tired herself out with trying, the poor little thing sat down and
cried.
`Come, there's no use in crying like that!' said Alice to
herself, rather sharply; `I advise you to leave off this minute!'
She generally gave herself very good advice, (though she very
seldom followed it), and sometimes she scolded herself so
severely as to bring tears into her eyes; and once she remembered
trying to box her own ears for having cheated herself in a game
of croquet she was playing against herself, for this curious
child was very fond of pretending to be two people. `But it's no
use now,' thought poor Alice, `to pretend to be two people! Why,
there's hardly enough of me left to make ONE respectable
person!'
Soon her eye fell on a little glass box that was lying under
the table: she opened it, and found in it a very small cake, on
which the words `EAT ME' were beautifully marked in currants.
`Well, I'll eat it,' said Alice, `and if it makes me grow larger,
I can reach the key; and if it makes me grow smaller, I can creep
under the door; so either way I'll get into the garden, and I
don't care which happens!'
She ate a little bit, and said anxiously to herself, `Which
way? Which way?', holding her hand on the top of her head to
feel which way it was growing, and she was quite surprised to
find that she remained the same size: to be sure, this generally
happens when one eats cake, but Alice had got so much into the
way of expecting nothing but out-of-the-way things to happen,
that it seemed quite dull and stupid for life to go on in the
common way.
So she set to work, and very soon finished off the cake.
CHAPTER II
The Pool of Tears
`Curiouser and curiouser!' cried Alice (she was so much
surprised, that for the moment she quite forgot how to speak good
English); `now I'm opening out like the largest telescope that
ever was! Good-bye, feet!' (for when she looked down at her
feet, they seemed to be almost out of sight, they were getting so
far off). `Oh, my poor little feet, I wonder who will put on
your shoes and stockings for you now, dears? I'm sure _I_ shan't
be able! I shall be a great deal too far off to trouble myself
about you: you must manage the best way you can; --but I must be
kind to them,' thought Alice, `or perhaps they won't walk the
way I want to go! Let me see: I'll give them a new pair of
boots every Christmas.'
And she went on planning to herself how she would manage it.
`They must go by the carrier,' she thought; `and how funny it'll
seem, sending presents to one's own feet! And how odd the
directions will look!
ALICE'S RIGHT FOOT, ESQ.
HEARTHRUG,
NEAR THE FENDER,
(WITH ALICE'S LOVE).
Oh dear, what nonsense I'm talking!'
Just then her head struck against the roof of the hall: in
fact she was now more than nine feet high, and she at once took
up the little golden key and hurried off to the garden door.
Poor Alice! It was as much as she could do, lying down on one
side, to look through into the garden with one eye; but to get
through was more hopeless than ever: she sat down and began to
cry again.
`You ought to be ashamed of yourself,' said Alice, `a great
girl like you,' (she might well say this), `to go on crying in
this way! Stop this moment, I tell you!' But she went on all
the same, shedding gallons of tears, until there was a large pool
all round her, about four inches deep and reaching half down the
hall.
After a time she heard a little pattering of feet in the
distance, and she hastily dried her eyes to see what was coming.
It was the White Rabbit returning, splendidly dressed, with a
pair of white kid gloves in one hand and a large fan in the
other: he came trotting along in a great hurry, muttering to
himself as he came, `Oh! the Duchess, the Duchess! Oh! won't she
be savage if I've kept her waiting!' Alice felt so desperate
that she was ready to ask help of any one; so, when the Rabbit
came near her, she began, in a low, timid voice, `If you please,
sir--' The Rabbit started violently, dropped the white kid
gloves and the fan, and skurried away into the darkness as hard
as he could go.
Alice took up the fan and gloves, and, as the hall was very
hot, she kept fanning herself all the time she went on talking:
`Dear, dear! How queer everything is to-day! And yesterday
things went on just as usual. I wonder if I've been changed in
the night? Let me think: was I the same when I got up this
morning? I almost think I can remember feeling a little
different. But if I'm not the same, the next question is, Who in
the world am I? Ah, THAT'S the great puzzle!' And she began
thinking over all the children she knew that were of the same age
as herself, to see if she could have been changed for any of
them.
`I'm sure I'm not Ada,' she said, `for her hair goes in such
long ringlets, and mine doesn't go in ringlets at all; and I'm
sure I can't be Mabel, for I know all sorts of things, and she,
oh! she knows such a very little! Besides, SHE'S she, and I'm I,
and--oh dear, how puzzling it all is! I'll try if I know all the
things I used to know. Let me see: four times five is twelve,
and four times six is thirteen, and four times seven is--oh dear!
I shall never get to twenty at that rate! However, the
Multiplication Table doesn't signify: let's try Geography.
London is the capital of Paris, and Paris is the capital of Rome,
and Rome--no, THAT'S all wrong, I'm certain! I must have been
changed for Mabel! I'll try and say "How doth the little--"'
and she crossed her hands on her lap as if she were saying lessons,
and began to repeat it, but her voice sounded hoarse and
strange, and the words did not come the same as they used to do:--
`How doth the little crocodile
Improve his shining tail,
And pour the waters of the Nile
On every golden scale!
`How cheerfully he seems to grin,
How neatly spread his claws,
And welcome little fishes in
With gently smiling jaws!'
`I'm sure those are not the right words,' said poor Alice, and
her eyes filled with tears again as she went on, `I must be Mabel
after all, and I shall have to go and live in that poky little
house, and have next to no toys to play with, and oh! ever so
many lessons to learn! No, I've made up my mind about it; if I'm
Mabel, I'll stay down here! It'll be no use their putting their
heads down and saying "Come up again, dear!" I shall only look
up and say "Who am I then? Tell me that first, and then, if I
like being that person, I'll come up: if not, I'll stay down
here till I'm somebody else"--but, oh dear!' cried Alice, with a
sudden burst of tears, `I do wish they WOULD put their heads
down! I am so VERY tired of being all alone here!'
As she said this she looked down at her hands, and was
surprised to see that she had put on one of the Rabbit's little
white kid gloves while she was talking. `How CAN I have done
that?' she thought. `I must be growing small again.' She got up
and went to the table to measure herself by it, and found that,
as nearly as she could guess, she was now about two feet high,
and was going on shrinking rapidly: she soon found out that the
cause of this was the fan she was holding, and she dropped it
hastily, just in time to avoid shrinking away altogether.
`That WAS a narrow escape!' said Alice, a good deal frightened at
the sudden change, but very glad to find herself still in
existence; `and now for the garden!' and she ran with all speed
back to the little door: but, alas! the little door was shut
again, and the little golden key was lying on the glass table as
before, `and things are worse than ever,' thought the poor child,
`for I never was so small as this before, never! And I declare
it's too bad, that it is!'
As she said these words her foot slipped, and in another
moment, splash! she was up to her chin in salt water. He first
idea was that she had somehow fallen into the sea, `and in that
case I can go back by railway,' she said to herself. (Alice had
been to the seaside once in her life, and had come to the general
conclusion, that wherever you go to on the English coast you find
a number of bathing machines in the sea, some children digging in
the sand with wooden spades, then a row of lodging houses, and
behind them a railway station.) However, she soon made out that
she was in the pool of tears which she had wept when she was nine
feet high.
`I wish I hadn't cried so much!' said Alice, as she swam about,
trying to find her way out. `I shall be punished for it now, I
suppose, by being drowned in my own tears! That WILL be a queer
thing, to be sure! However, everything is queer to-day.'
Just then she heard something splashing about in the pool a
little way off, and she swam nearer to make out what it was: at
first she thought it must be a walrus or hippopotamus, but then
she remembered how small she was now, and she soon made out that
it was only a mouse that had slipped in like herself.
`Would it be of any use, now,' thought Alice, `to speak to this
mouse? Everything is so out-of-the-way down here, that I should
think very likely it can talk: at any rate, there's no harm in
trying.' So she began: `O Mouse, do you know the way out of
this pool? I am very tired of swimming about here, O Mouse!'
(Alice thought this must be the right way of speaking to a mouse:
she had never done such a thing before, but she remembered having
seen in her brother's Latin Grammar, `A mouse--of a mouse--to a
mouse--a mouse--O mouse!' The Mouse looked at her rather
inquisitively, and seemed to her to wink with one of its little
eyes, but it said nothing.
`Perhaps it doesn't understand English,' thought Alice; `I
daresay it's a French mouse, come over with William the
Conqueror.' (For, with all her knowledge of history, Alice had
no very clear notion how long ago anything had happened.) So she
began again: `Ou est ma chatte?' which was the first sentence in
her French lesson-book. The Mouse gave a sudden leap out of the
water, and seemed to quiver all over with fright. `Oh, I beg
your pardon!' cried Alice hastily, afraid that she had hurt the
poor animal's feelings. `I quite forgot you didn't like cats.'
`Not like cats!' cried the Mouse, in a shrill, passionate
voice. `Would YOU like cats if you were me?'
`Well, perhaps not,' said Alice in a soothing tone: `don't be
angry about it. And yet I wish I could show you our cat Dinah:
I think you'd take a fancy to cats if you could only see her.
She is such a dear quiet thing,' Alice went on, half to herself,
as she swam lazily about in the pool, `and she sits purring so
nicely by the fire, licking her paws and washing her face--and
she is such a nice soft thing to nurse--and she's such a capital
one for catching mice--oh, I beg your pardon!' cried Alice again,
for this time the Mouse was bristling all over, and she felt
certain it must be really offended. `We won't talk about her any
more if you'd rather not.'
`We indeed!' cried the Mouse, who was trembling down to the end
of his tail. `As if I would talk on such a subject! Our family
always HATED cats: nasty, low, vulgar things! Don't let me hear
the name again!'
`I won't indeed!' said Alice, in a great hurry to change the
subject of conversation. `Are you--are you fond--of--of dogs?'
The Mouse did not answer, so Alice went on eagerly: `There is
such a nice little dog near our house I should like to show you!
A little bright-eyed terrier, you know, with oh, such long curly
brown hair! And it'll fetch things when you throw them, and
it'll sit up and beg for its dinner, and all sorts of things--I
can't remember half of them--and it belongs to a farmer, you
know, and he says it's so useful, it's worth a hundred pounds!
He says it kills all the rats and--oh dear!' cried Alice in a
sorrowful tone, `I'm afraid I've offended it again!' For the
Mouse was swimming away from her as hard as it could go, and
making quite a commotion in the pool as it went.
So she called softly after it, `Mouse dear! Do come back
again, and we won't talk about cats or dogs either, if you don't
like them!' When the Mouse heard this, it turned round and swam
slowly back to her: its face was quite pale (with passion, Alice
thought), and it said in a low trembling voice, `Let us get to
the shore, and then I'll tell you my history, and you'll
understand why it is I hate cats and dogs.'
It was high time to go, for the pool was getting quite crowded
with the birds and animals that had fallen into it: there were a
Duck and a Dodo, a Lory and an Eaglet, and several other curious
creatures. Alice led the way, and the whole party swam to the
shore.
CHAPTER III
A Caucus-Race and a Long Tale
They were indeed a queer-looking party that assembled on the
bank--the birds with draggled feathers, the animals with their
fur clinging close to them, and all dripping wet, cross, and
uncomfortable.
The first question of course was, how to get dry again: they
had a consultation about this, and after a few minutes it seemed
quite natural to Alice to find herself talking familiarly with
them, as if she had known them all her life. Indeed, she had
quite a long argument with the Lory, who at last turned sulky,
and would only say, `I am older than you, and must know better';
and this Alice would not allow without knowing how old it was,
and, as the Lory positively refused to tell its age, there was no
more to be said.
At last the Mouse, who seemed to be a person of authority among
them, called out, `Sit down, all of you, and listen to me! I'LL
soon make you dry enough!' They all sat down at once, in a large
ring, with the Mouse in the middle. Alice kept her eyes
anxiously fixed on it, for she felt sure she would catch a bad
cold if she did not get dry very soon.
`Ahem!' said the Mouse with an important air, `are you all ready?
This is the driest thing I know. Silence all round, if you please!
"William the Conqueror, whose cause was favoured by the pope, was
soon submitted to by the English, who wanted leaders, and had been
of late much accustomed to usurpation and conquest. Edwin and
Morcar, the earls of Mercia and Northumbria--"'
`Ugh!' said the Lory, with a shiver.
`I beg your pardon!' said the Mouse, frowning, but very
politely: `Did you speak?'
`Not I!' said the Lory hastily.
`I thought you did,' said the Mouse. `--I proceed. "Edwin and
Morcar, the earls of Mercia and Northumbria, declared for him:
and even Stigand, the patriotic archbishop of Canterbury, found
it advisable--"'
`Found WHAT?' said the Duck.
`Found IT,' the Mouse replied rather crossly: `of course you
know what "it" means.'
`I know what "it" means well enough, when I find a thing,' said
the Duck: `it's generally a frog or a worm. The question is,
what did the archbishop find?'
The Mouse did not notice this question, but hurriedly went on,
`"--found it advisable to go with Edgar Atheling to meet William
and offer him the crown. William's conduct at first was
moderate. But the insolence of his Normans--" How are you
getting on now, my dear?' it continued, turning to Alice as it
spoke.
`As wet as ever,' said Alice in a melancholy tone: `it doesn't
seem to dry me at all.'
`In that case,' said the Dodo solemnly, rising to its feet, `I
move that the meeting adjourn, for the immediate adoption of more
energetic remedies--'
`Speak English!' said the Eaglet. `I don't know the meaning of
half those long words, and, what's more, I don't believe you do
either!' And the Eaglet bent down its head to hide a smile:
some of the other birds tittered audibly.
`What I was going to say,' said the Dodo in an offended tone,
`was, that the best thing to get us dry would be a Caucus-race.'
`What IS a Caucus-race?' said Alice; not that she wanted much
to know, but the Dodo had paused as if it thought that SOMEBODY
ought to speak, and no one else seemed inclined to say anything.
`Why,' said the Dodo, `the best way to explain it is to do it.'
(And, as you might like to try the thing yourself, some winter
day, I will tell you how the Dodo managed it.)
First it marked out a race-course, in a sort of circle, (`the
exact shape doesn't matter,' it said,) and then all the party
were placed along the course, here and there. There was no `One,
two, three, and away,' but they began running when they liked,
and left off when they liked, so that it was not easy to know
when the race was over. However, when they had been running half
an hour or so, and were quite dry again, the Dodo suddenly called
out `The race is over!' and they all crowded round it, panting,
and asking, `But who has won?'
This question the Dodo could not answer without a great deal of
thought, and it sat for a long time with one finger pressed upon
its forehead (the position in which you usually see Shakespeare,
in the pictures of him), while the rest waited in silence. At
last the Dodo said, `EVERYBODY has won, and all must have
prizes.'
`But who is to give the prizes?' quite a chorus of voices
asked.
`Why, SHE, of course,' said the Dodo, pointing to Alice with
one finger; and the whole party at once crowded round her,
calling out in a confused way, `Prizes! Prizes!'
Alice had no idea what to do, and in despair she put her hand
in her pocket, and pulled out a box of comfits, (luckily the salt
water had not got into it), and handed them round as prizes.
There was exactly one a-piece all round.
`But she must have a prize herself, you know,' said the Mouse.
`Of course,' the Dodo replied very gravely. `What else have
you got in your pocket?' he went on, turning to Alice.
`Only a thimble,' said Alice sadly.
`Hand it over here,' said the Dodo.
Then they all crowded round her once more, while the Dodo
solemnly presented the thimble, saying `We beg your acceptance of
this elegant thimble'; and, when it had finished this short
speech, they all cheered.
Alice thought the whole thing very absurd, but they all looked
so grave that she did not dare to laugh; and, as she could not
think of anything to say, she simply bowed, and took the thimble,
looking as solemn as she could.
The next thing was to eat the comfits: this caused some noise
and confusion, as the large birds complained that they could not
taste theirs, and the small ones choked and had to be patted on
the back. However, it was over at last, and they sat down again
in a ring, and begged the Mouse to tell them something more.
`You promised to tell me your history, you know,' said Alice,
`and why it is you hate--C and D,' she added in a whisper, half
afraid that it would be offended again.
`Mine is a long and a sad tale!' said the Mouse, turning to
Alice, and sighing.
`It IS a long tail, certainly,' said Alice, looking down with
wonder at the Mouse's tail; `but why do you call it sad?' And
she kept on puzzling about it while the Mouse was speaking, so
that her idea of the tale was something like this:--
`Fury said to a
mouse, That he
met in the
house,
"Let us
both go to
law: I will
prosecute
YOU. --Come,
I'll take no
denial; We
must have a
trial: For
really this
morning I've
nothing
to do."
Said the
mouse to the
cur, "Such
a trial,
dear Sir,
With
no jury
or judge,
would be
wasting
our
breath."
"I'll be
judge, I'll
be jury,"
Said
cunning
old Fury:
"I'll
try the
whole
cause,
and
condemn
you
to
death."'
`You are not attending!' said the Mouse to Alice severely.
`What are you thinking of?'
`I beg your pardon,' said Alice very humbly: `you had got to
the fifth bend, I think?'
`I had NOT!' cried the Mouse, sharply and very angrily.
`A knot!' said Alice, always ready to make herself useful, and
looking anxiously about her. `Oh, do let me help to undo it!'
`I shall do nothing of the sort,' said the Mouse, getting up
and walking away. `You insult me by talking such nonsense!'
`I didn't mean it!' pleaded poor Alice. `But you're so easily
offended, you know!'
The Mouse only growled in reply.
`Please come back and finish your story!' Alice called after
it; and the others all joined in chorus, `Yes, please do!' but
the Mouse only shook its head impatiently, and walked a little
quicker.
`What a pity it wouldn't stay!' sighed the Lory, as soon as it
was quite out of sight; and an old Crab took the opportunity of
saying to her daughter `Ah, my dear! Let this be a lesson to you
never to lose YOUR temper!' `Hold your tongue, Ma!' said the
young Crab, a little snappishly. `You're enough to try the
patience of an oyster!'
`I wish I had our Dinah here, I know I do!' said Alice aloud,
addressing nobody in particular. `She'd soon fetch it back!'
`And who is Dinah, if I might venture to ask the question?'
said the Lory.
Alice replied eagerly, for she was always ready to talk about
her pet: `Dinah's our cat. And she's such a capital one for
catching mice you can't think! And oh, I wish you could see her
after the birds! Why, she'll eat a little bird as soon as look
at it!'
This speech caused a remarkable sensation among the party.
Some of the birds hurried off at once: one the old Magpie began
wrapping itself up very carefully, remarking, `I really must be
getting home; the night-air doesn't suit my throat!' and a Canary
called out in a trembling voice to its children, `Come away, my
dears! It's high time you were all in bed!' On various pretexts
they all moved off, and Alice was soon left alone.
`I wish I hadn't mentioned Dinah!' she said to herself in a
melancholy tone. `Nobody seems to like her, down here, and I'm
sure she's the best cat in the world! Oh, my dear Dinah! I
wonder if I shall ever see you any more!' And here poor Alice
began to cry again, for she felt very lonely and low-spirited.
In a little while, however, she again heard a little pattering of
footsteps in the distance, and she looked up eagerly, half hoping
that the Mouse had changed his mind, and was coming back to
finish his story.
CHAPTER IV
The Rabbit Sends in a Little Bill
It was the White Rabbit, trotting slowly back again, and
looking anxiously about as it went, as if it had lost something;
and she heard it muttering to itself `The Duchess! The Duchess!
Oh my dear paws! Oh my fur and whiskers! She'll get me
executed, as sure as ferrets are ferrets! Where CAN I have
dropped them, I wonder?' Alice guessed in a moment that it was
looking for the fan and the pair of white kid gloves, and she
very good-naturedly began hunting about for them, but they were
nowhere to be seen--everything seemed to have changed since her
swim in the pool, and the great hall, with the glass table and
the little door, had vanished completely.
Very soon the Rabbit noticed Alice, as she went hunting about,
and called out to her in an angry tone, `Why, Mary Ann, what ARE
you doing out here? Run home this moment, and fetch me a pair of
gloves and a fan! Quick, now!' And Alice was so much frightened
that she ran off at once in the direction it pointed to, without
trying to explain the mistake it had made.
`He took me for his housemaid,' she said to herself as she ran.
`How surprised he'll be when he finds out who I am! But I'd
better take him his fan and gloves--that is, if I can find them.'
As she said this, she came upon a neat little house, on the door
of which was a bright brass plate with the name `W. RABBIT'
engraved upon it. She went in without knocking, and hurried
upstairs, in great fear lest she should meet the real Mary Ann,
and be turned out of the house before she had found the fan and
gloves.
`How queer it seems,' Alice said to herself, `to be going
messages for a rabbit! I suppose Dinah'll be sending me on
messages next!' And she began fancying the sort of thing that
would happen: `"Miss Alice! Come here directly, and get ready
for your walk!" "Coming in a minute, nurse! But I've got to see
that the mouse doesn't get out." Only I don't think,' Alice went
on, `that they'd let Dinah stop in the house if it began ordering
people about like that!'
By this time she had found her way into a tidy little room with
a table in the window, and on it (as she had hoped) a fan and two
or three pairs of tiny white kid gloves: she took up the fan and
a pair of the gloves, and was just going to leave the room, when
her eye fell upon a little bottle that stood near the looking-
glass. There was no label this time with the words `DRINK ME,'
but nevertheless she uncorked it and put it to her lips. `I know
SOMETHING interesting is sure to happen,' she said to herself,
`whenever I eat or drink anything; so I'll just see what this
bottle does. I do hope it'll make me grow large again, for
really I'm quite tired of being such a tiny little thing!'
It did so indeed, and much sooner than she had expected:
before she had drunk half the bottle, she found her head pressing
against the ceiling, and had to stoop to save her neck from being
broken. She hastily put down the bottle, saying to herself
`That's quite enough--I hope I shan't grow any more--As it is, I
can't get out at the door--I do wish I hadn't drunk quite so
much!'
Alas! it was too late to wish that! She went on growing, and
growing, and very soon had to kneel down on the floor: in
another minute there was not even room for this, and she tried
the effect of lying down with one elbow against the door, and the
other arm curled round her head. Still she went on growing, and,
as a last resource, she put one arm out of the window, and one
foot up the chimney, and said to herself `Now I can do no more,
whatever happens. What WILL become of me?'
Luckily for Alice, the little magic bottle had now had its full
effect, and she grew no larger: still it was very uncomfortable,
and, as there seemed to be no sort of chance of her ever getting
out of the room again, no wonder she felt unhappy.
`It was much pleasanter at home,' thought poor Alice, `when one
wasn't always growing larger and smaller, and being ordered about
by mice and rabbits. I almost wish I hadn't gone down that
rabbit-hole--and yet--and yet--it's rather curious, you know,
this sort of life! I do wonder what CAN have happened to me!
When I used to read fairy-tales, I fancied that kind of thing
never happened, and now here I am in the middle of one! There
ought to be a book written about me, that there ought! And when
I grow up, I'll write one--but I'm grown up now,' she added in a
sorrowful tone; `at least there's no room to grow up any more
HERE.'
`But then,' thought Alice, `shall I NEVER get any older than I
am now? That'll be a comfort, one way--never to be an old woman-
-but then--always to have lessons to learn! Oh, I shouldn't like
THAT!'
`Oh, you foolish Alice!' she answered herself. `How can you
learn lessons in here? Why, there's hardly room for YOU, and no
room at all for any lesson-books!'
And so she went on, taking first one side and then the other,
and making quite a conversation of it altogether; but after a few
minutes she heard a voice outside, and stopped to listen.
`Mary Ann! Mary Ann!' said the voice. `Fetch me my gloves
this moment!' Then came a little pattering of feet on the
stairs. Alice knew it was the Rabbit coming to look for her, and
she trembled till she shook the house, quite forgetting that she
was now about a thousand times as large as the Rabbit, and had no
reason to be afraid of it.
Presently the Rabbit came up to the door, and tried to open it;
but, as the door opened inwards, and Alice's elbow was pressed
hard against it, that attempt proved a failure. Alice heard it
say to itself `Then I'll go round and get in at the window.'
`THAT you won't' thought Alice, and, after waiting till she
fancied she heard the Rabbit just under the window, she suddenly
spread out her hand, and made a snatch in the air. She did not
get hold of anything, but she heard a little shriek and a fall,
and a crash of broken glass, from which she concluded that it was
just possible it had fallen into a cucumber-frame, or something
of the sort.
Next came an angry voice--the Rabbit's--`Pat! Pat! Where are
you?' And then a voice she had never heard before, `Sure then
I'm here! Digging for apples, yer honour!'
`Digging for apples, indeed!' said the Rabbit angrily. `Here!
Come and help me out of THIS!' (Sounds of more broken glass.)
`Now tell me, Pat, what's that in the window?'
`Sure, it's an arm, yer honour!' (He pronounced it `arrum.')
`An arm, you goose! Who ever saw one that size? Why, it
fills the whole window!'
`Sure, it does, yer honour: but it's an arm for all that.'
`Well, it's got no business there, at any rate: go and take it
away!'
There was a long silence after this, and Alice could only hear
whispers now and then; such as, `Sure, I don't like it, yer
honour, at all, at all!' `Do as I tell you, you coward!' and at
last she spread out her hand again, and made another snatch in
the air. This time there were TWO little shrieks, and more
sounds of broken glass. `What a number of cucumber-frames there
must be!' thought Alice. `I wonder what they'll do next! As for
pulling me out of the window, I only wish they COULD! I'm sure I
don't want to stay in here any longer!'
She waited for some time without hearing anything more: at
last came a rumbling of little cartwheels, and the sound of a
good many voice all talking together: she made out the words:
`Where's the other ladder?--Why, I hadn't to bring but one;
Bill's got the other--Bill! fetch it here, lad!--Here, put 'em up
at this corner--No, tie 'em together first--they don't reach half
high enough yet--Oh! they'll do well enough; don't be particular-
-Here, Bill! catch hold of this rope--Will the roof bear?--Mind
that loose slate--Oh, it's coming down! Heads below!' (a loud
crash)--`Now, who did that?--It was Bill, I fancy--Who's to go
down the chimney?--Nay, I shan't! YOU do it!--That I won't,
then!--Bill's to go down--Here, Bill! the master says you're to
go down the chimney!'
`Oh! So Bill's got to come down the chimney, has he?' said
Alice to herself. `Shy, they seem to put everything upon Bill!
I wouldn't be in Bill's place for a good deal: this fireplace is
narrow, to be sure; but I THINK I can kick a little!'
She drew her foot as far down the chimney as she could, and
waited till she heard a little animal (she couldn't guess of what
sort it was) scratching and scrambling about in the chimney close
above her: then, saying to herself `This is Bill,' she gave one
sharp kick, and waited to see what would happen next.
The first thing she heard was a general chorus of `There goes
Bill!' then the Rabbit's voice along--`Catch him, you by the
hedge!' then silence, and then another confusion of voices--`Hold
up his head--Brandy now--Don't choke him--How was it, old fellow?
What happened to you? Tell us all about it!'
Last came a little feeble, squeaking voice, (`That's Bill,'
thought Alice,) `Well, I hardly know--No more, thank ye; I'm
better now--but I'm a deal too flustered to tell you--all I know
is, something comes at me like a Jack-in-the-box, and up I goes
like a sky-rocket!'
`So you did, old fellow!' said the others.
`We must burn the house down!' said the Rabbit's voice; and
Alice called out as loud as she could, `If you do. I'll set
Dinah at you!'
There was a dead silence instantly, and Alice thought to
herself, `I wonder what they WILL do next! If they had any
sense, they'd take the roof off.' After a minute or two, they
began moving about again, and Alice heard the Rabbit say, `A
barrowful will do, to begin with.'
`A barrowful of WHAT?' thought Alice; but she had not long to
doubt, for the next moment a shower of little pebbles came
rattling in at the window, and some of them hit her in the face.
`I'll put a stop to this,' she said to herself, and shouted out,
`You'd better not do that again!' which produced another dead
silence.
Alice noticed with some surprise that the pebbles were all
turning into little cakes as they lay on the floor, and a bright
idea came into her head. `If I eat one of these cakes,' she
thought, `it's sure to make SOME change in my size; and as it
can't possibly make me larger, it must make me smaller, I
suppose.'
So she swallowed one of the cakes, and was delighted to find
that she began shrinking directly. As soon as she was small
enough to get through the door, she ran out of the house, and
found quite a crowd of little animals and birds waiting outside.
The poor little Lizard, Bill, was in the middle, being held up by
two guinea-pigs, who were giving it something out of a bottle.
They all made a rush at Alice the moment she appeared; but she
ran off as hard as she could, and soon found herself safe in a
thick wood.
`The first thing I've got to do,' said Alice to herself, as she
wandered about in the wood, `is to grow to my right size again;
and the second thing is to find my way into that lovely garden.
I think that will be the best plan.'
It sounded an excellent plan, no doubt, and very neatly and
simply arranged; the only difficulty was, that she had not the
smallest idea how to set about it; and while she was peering
about anxiously among the trees, a little sharp bark just over
her head made her look up in a great hurry.
An enormous puppy was looking down at her with large round
eyes, and feebly stretching out one paw, trying to touch her.
`Poor little thing!' said Alice, in a coaxing tone, and she tried
hard to whistle to it; but she was terribly frightened all the
time at the thought that it might be hungry, in which case it
would be very likely to eat her up in spite of all her coaxing.
Hardly knowing what she did, she picked up a little bit of
stick, and held it out to the puppy; whereupon the puppy jumped
into the air off all its feet at once, with a yelp of delight,
and rushed at the stick, and made believe to worry it; then Alice
dodged behind a great thistle, to keep herself from being run
over; and the moment she appeared on the other side, the puppy
made another rush at the stick, and tumbled head over heels in
its hurry to get hold of it; then Alice, thinking it was very
like having a game of play with a cart-horse, and expecting every
moment to be trampled under its feet, ran round the thistle
again; then the puppy began a series of short charges at the
stick, running a very little way forwards each time and a long
way back, and barking hoarsely all the while, till at last it sat
down a good way off, panting, with its tongue hanging out of its
mouth, and its great eyes half shut.
This seemed to Alice a good opportunity for making her escape;
so she set off at once, and ran till she was quite tired and out
of breath, and till the puppy's bark sounded quite faint in the
distance.
`And yet what a dear little puppy it was!' said Alice, as she
leant against a buttercup to rest herself, and fanned herself
with one of the leaves: `I should have liked teaching it tricks
very much, if--if I'd only been the right size to do it! Oh
dear! I'd nearly forgotten that I've got to grow up again! Let
me see--how IS it to be managed? I suppose I ought to eat or
drink something or other; but the great question is, what?'
The great question certainly was, what? Alice looked all round
her at the flowers and the blades of grass, but she did not see
anything that looked like the right thing to eat or drink under
the circumstances. There was a large mushroom growing near her,
about the same height as herself; and when she had looked under
it, and on both sides of it, and behind it, it occurred to her
that she might as well look and see what was on the top of it.
She stretched herself up on tiptoe, and peeped over the edge of
the mushroom, and her eyes immediately met those of a large
caterpillar, that was sitting on the top with its arms folded,
quietly smoking a long hookah, and taking not the smallest notice
of her or of anything else.
CHAPTER V
Advice from a Caterpillar
The Caterpillar and Alice looked at each other for some time in
silence: at last the Caterpillar took the hookah out of its
mouth, and addressed her in a languid, sleepy voice.
`Who are YOU?' said the Caterpillar.
This was not an encouraging opening for a conversation. Alice
replied, rather shyly, `I--I hardly know, sir, just at present--
at least I know who I WAS when I got up this morning, but I think
I must have been changed several times since then.'
`What do you mean by that?' said the Caterpillar sternly.
`Explain yourself!'
`I can't explain MYSELF, I'm afraid, sir' said Alice, `because
I'm not myself, you see.'
`I don't see,' said the Caterpillar.
`I'm afraid I can't put it more clearly,' Alice replied very
politely, `for I can't understand it myself to begin with; and
being so many different sizes in a day is very confusing.'
`It isn't,' said the Caterpillar.
`Well, perhaps you haven't found it so yet,' said Alice; `but
when you have to turn into a chrysalis--you will some day, you
know--and then after that into a butterfly, I should think you'll
feel it a little queer, won't you?'
`Not a bit,' said the Caterpillar.
`Well, perhaps your feelings may be different,' said Alice;
`all I know is, it would feel very queer to ME.'
`You!' said the Caterpillar contemptuously. `Who are YOU?'
Which brought them back again to the beginning of the
conversation. Alice felt a little irritated at the Caterpillar's
making such VERY short remarks, and she drew herself up and said,
very gravely, `I think, you ought to tell me who YOU are, first.'
`Why?' said the Caterpillar.
Here was another puzzling question; and as Alice could not
think of any good reason, and as the Caterpillar seemed to be in
a VERY unpleasant state of mind, she turned away.
`Come back!' the Caterpillar called after her. `I've something
important to say!'
This sounded promising, certainly: Alice turned and came back
again.
`Keep your temper,' said the Caterpillar.
`Is that all?' said Alice, swallowing down her anger as well as
she could.
`No,' said the Caterpillar.
Alice thought she might as well wait, as she had nothing else
to do, and perhaps after all it might tell her something worth
hearing. For some minutes it puffed away without speaking, but
at last it unfolded its arms, took the hookah out of its mouth
again, and said, `So you think you're changed, do you?'
`I'm afraid I am, sir,' said Alice; `I can't remember things as
I used--and I don't keep the same size for ten minutes together!'
`Can't remember WHAT things?' said the Caterpillar.
`Well, I've tried to say "HOW DOTH THE LITTLE BUSY BEE," but it
all came different!' Alice replied in a very melancholy voice.
`Repeat, "YOU ARE OLD, FATHER WILLIAM,"' said the Caterpillar.
Alice folded her hands, and began:--
`You are old, Father William,' the young man said,
`And your hair has become very white;
And yet you incessantly stand on your head--
Do you think, at your age, it is right?'
`In my youth,' Father William replied to his son,
`I feared it might injure the brain;
But, now that I'm perfectly sure I have none,
Why, I do it again and again.'
`You are old,' said the youth, `as I mentioned before,
And have grown most uncommonly fat;
Yet you turned a back-somersault in at the door--
Pray, what is the reason of that?'
`In my youth,' said the sage, as he shook his grey locks,
`I kept all my limbs very supple
By the use of this ointment--one shilling the box--
Allow me to sell you a couple?'
`You are old,' said the youth, `and your jaws are too weak
For anything tougher than suet;
Yet you finished the goose, with the bones and the beak--
Pray how did you manage to do it?'
`In my youth,' said his father, `I took to the law,
And argued each case with my wife;
And the muscular strength, which it gave to my jaw,
Has lasted the rest of my life.'
`You are old,' said the youth, `one would hardly suppose
That your eye was as steady as ever;
Yet you balanced an eel on the end of your nose--
What made you so awfully clever?'
`I have answered three questions, and that is enough,'
Said his father; `don't give yourself airs!
Do you think I can listen all day to such stuff?
Be off, or I'll kick you down stairs!'
`That is not said right,' said the Caterpillar.
`Not QUITE right, I'm afraid,' said Alice, timidly; `some of the
words have got altered.'
`It is wrong from beginning to end,' said the Caterpillar
decidedly, and there was silence for some minutes.
The Caterpillar was the first to speak.
`What size do you want to be?' it asked.
`Oh, I'm not particular as to size,' Alice hastily replied;
`only one doesn't like changing so often, you know.'
`I DON'T know,' said the Caterpillar.
Alice said nothing: she had never been so much contradicted in
her life before, and she felt that she was losing her temper.
`Are you content now?' said the Caterpillar.
`Well, I should like to be a LITTLE larger, sir, if you
wouldn't mind,' said Alice: `three inches is such a wretched
height to be.'
`It is a very good height indeed!' said the Caterpillar
angrily, rearing itself upright as it spoke (it was exactly three
inches high).
`But I'm not used to it!' pleaded poor Alice in a piteous tone.
And she thought of herself, `I wish the creatures wouldn't be so
easily offended!'
`You'll get used to it in time,' said the Caterpillar; and it
put the hookah into its mouth and began smoking again.
This time Alice waited patiently until it chose to speak again.
In a minute or two the Caterpillar took the hookah out of its
mouth and yawned once or twice, and shook itself. Then it got
down off the mushroom, and crawled away in the grass, merely
remarking as it went, `One side will make you grow taller, and
the other side will make you grow shorter.'
`One side of WHAT? The other side of WHAT?' thought Alice to
herself.
`Of the mushroom,' said the Caterpillar, just as if she had
asked it aloud; and in another moment it was out of sight.
Alice remained looking thoughtfully at the mushroom for a
minute, trying to make out which were the two sides of it; and as
it was perfectly round, she found this a very difficult question.
However, at last she stretched her arms round it as far as they
would go, and broke off a bit of the edge with each hand.
`And now which is which?' she said to herself, and nibbled a
little of the right-hand bit to try the effect: the next moment
she felt a violent blow underneath her chin: it had struck her
foot!
She was a good deal frightened by this very sudden change, but
she felt that there was no time to be lost, as she was shrinking
rapidly; so she set to work at once to eat some of the other bit.
Her chin was pressed so closely against her foot, that there was
hardly room to open her mouth; but she did it at last, and
managed to swallow a morsel of the lefthand bit.
* * * * * * *
* * * * * *
* * * * * * *
`Come, my head's free at last!' said Alice in a tone of
delight, which changed into alarm in another moment, when she
found that her shoulders were nowhere to be found: all she could
see, when she looked down, was an immense length of neck, which
seemed to rise like a stalk out of a sea of green leaves that lay
far below her.
`What CAN all that green stuff be?' said Alice. `And where
HAVE my shoulders got to? And oh, my poor hands, how is it I
can't see you?' She was moving them about as she spoke, but no
result seemed to follow, except a little shaking among the
distant green leaves.
As there seemed to be no chance of getting her hands up to her
head, she tried to get her head down to them, and was delighted
to find that her neck would bend about easily in any direction,
like a serpent. She had just succeeded in curving it down into a
graceful zigzag, and was going to dive in among the leaves, which
she found to be nothing but the tops of the trees under which she
had been wandering, when a sharp hiss made her draw back in a
hurry: a large pigeon had flown into her face, and was beating
her violently with its wings.
`Serpent!' screamed the Pigeon.
`I'm NOT a serpent!' said Alice indignantly. `Let me alone!'
`Serpent, I say again!' repeated the Pigeon, but in a more
subdued tone, and added with a kind of sob, `I've tried every
way, and nothing seems to suit them!'
`I haven't the least idea what you're talking about,' said
Alice.
`I've tried the roots of trees, and I've tried banks, and I've
tried hedges,' the Pigeon went on, without attending to her; `but
those serpents! There's no pleasing them!'
Alice was more and more puzzled, but she thought there was no
use in saying anything more till the Pigeon had finished.
`As if it wasn't trouble enough hatching the eggs,' said the
Pigeon; `but I must be on the look-out for serpents night and
day! Why, I haven't had a wink of sleep these three weeks!'
`I'm very sorry you've been annoyed,' said Alice, who was
beginning to see its meaning.
`And just as I'd taken the highest tree in the wood,' continued
the Pigeon, raising its voice to a shriek, `and just as I was
thinking I should be free of them at last, they must needs come
wriggling down from the sky! Ugh, Serpent!'
`But I'm NOT a serpent, I tell you!' said Alice. `I'm a--I'm
a--'
`Well! WHAT are you?' said the Pigeon. `I can see you're
trying to invent something!'
`I--I'm a little girl,' said Alice, rather doubtfully, as she
remembered the number of changes she had gone through that day.
`A likely story indeed!' said the Pigeon in a tone of the
deepest contempt. `I've seen a good many little girls in my
time, but never ONE with such a neck as that! No, no! You're a
serpent; and there's no use denying it. I suppose you'll be
telling me next that you never tasted an egg!'
`I HAVE tasted eggs, certainly,' said Alice, who was a very
truthful child; `but little girls eat eggs quite as much as
serpents do, you know.'
`I don't believe it,' said the Pigeon; `but if they do, why
then they're a kind of serpent, that's all I can say.'
This was such a new idea to Alice, that she was quite silent
for a minute or two, which gave the Pigeon the opportunity of
adding, `You're looking for eggs, I know THAT well enough; and
what does it matter to me whether you're a little girl or a
serpent?'
`It matters a good deal to ME,' said Alice hastily; `but I'm
not looking for eggs, as it happens; and if I was, I shouldn't
want YOURS: I don't like them raw.'
`Well, be off, then!' said the Pigeon in a sulky tone, as it
settled down again into its nest. Alice crouched down among the
trees as well as she could, for her neck kept getting entangled
among the branches, and every now and then she had to stop and
untwist it. After a while she remembered that she still held the
pieces of mushroom in her hands, and she set to work very
carefully, nibbling first at one and then at the other, and
growing sometimes taller and sometimes shorter, until she had
succeeded in bringing herself down to her usual height.
It was so long since she had been anything near the right size,
that it felt quite strange at first; but she got used to it in a
few minutes, and began talking to herself, as usual. `Come,
there's half my plan done now! How puzzling all these changes
are! I'm never sure what I'm going to be, from one minute to
another! However, I've got back to my right size: the next
thing is, to get into that beautiful garden--how IS that to be
done, I wonder?' As she said this, she came suddenly upon an
open place, with a little house in it about four feet high.
`Whoever lives there,' thought Alice, `it'll never do to come
upon them THIS size: why, I should frighten them out of their
wits!' So she began nibbling at the righthand bit again, and did
not venture to go near the house till she had brought herself
down to nine inches high.
CHAPTER VI
Pig and Pepper
For a minute or two she stood looking at the house, and
wondering what to do next, when suddenly a footman in livery came
running out of the wood--(she considered him to be a footman
because he was in livery: otherwise, judging by his face only,
she would have called him a fish)--and rapped loudly at the door
with his knuckles. It was opened by another footman in livery,
with a round face, and large eyes like a frog; and both footmen,
Alice noticed, had powdered hair that curled all over their
heads. She felt very curious to know what it was all about, and
crept a little way out of the wood to listen.
The Fish-Footman began by producing from under his arm a great
letter, nearly as large as himself, and this he handed over to
the other, saying, in a solemn tone, `For the Duchess. An
invitation from the Queen to play croquet.' The Frog-Footman
repeated, in the same solemn tone, only changing the order of the
words a little, `From the Queen. An invitation for the Duchess
to play croquet.'
Then they both bowed low, and their curls got entangled
together.
Alice laughed so much at this, that she had to run back into
the wood for fear of their hearing her; and when she next peeped
out the Fish-Footman was gone, and the other was sitting on the
ground near the door, staring stupidly up into the sky.
Alice went timidly up to the door, and knocked.
`There's no sort of use in knocking,' said the Footman, `and
that for two reasons. First, because I'm on the same side of the
door as you are; secondly, because they're making such a noise
inside, no one could possibly hear you.' And certainly there was
a most extraordinary noise going on within--a constant howling
and sneezing, and every now and then a great crash, as if a dish
or kettle had been broken to pieces.
`Please, then,' said Alice, `how am I to get in?'
`There might be some sense in your knocking,' the Footman went
on without attending to her, `if we had the door between us. For
instance, if you were INSIDE, you might knock, and I could let
you out, you know.' He was looking up into the sky all the time
he was speaking, and this Alice thought decidedly uncivil. `But
perhaps he can't help it,' she said to herself; `his eyes are so
VERY nearly at the top of his head. But at any rate he might
answer questions.--How am I to get in?' she repeated, aloud.
`I shall sit here,' the Footman remarked, `till tomorrow--'
At this moment the door of the house opened, and a large plate
came skimming out, straight at the Footman's head: it just
grazed his nose, and broke to pieces against one of the trees
behind him.
`--or next day, maybe,' the Footman continued in the same tone,
exactly as if nothing had happened.
`How am I to get in?' asked Alice again, in a louder tone.
`ARE you to get in at all?' said the Footman. `That's the
first question, you know.'
It was, no doubt: only Alice did not like to be told so.
`It's really dreadful,' she muttered to herself, `the way all the
creatures argue. It's enough to drive one crazy!'
The Footman seemed to think this a good opportunity for
repeating his remark, with variations. `I shall sit here,' he
said, `on and off, for days and days.'
`But what am I to do?' said Alice.
`Anything you like,' said the Footman, and began whistling.
`Oh, there's no use in talking to him,' said Alice desperately:
`he's perfectly idiotic!' And she opened the door and went in.
The door led right into a large kitchen, which was full of
smoke from one end to the other: the Duchess was sitting on a
three-legged stool in the middle, nursing a baby; the cook was
leaning over the fire, stirring a large cauldron which seemed to
be full of soup.
`There's certainly too much pepper in that soup!' Alice said to
herself, as well as she could for sneezing.
There was certainly too much of it in the air. Even the
Duchess sneezed occasionally; and as for the baby, it was
sneezing and howling alternately without a moment's pause. The
only things in the kitchen that did not sneeze, were the cook,
and a large cat which was sitting on the hearth and grinning from
ear to ear.
`Please would you tell me,' said Alice, a little timidly, for
she was not quite sure whether it was good manners for her to
speak first, `why your cat grins like that?'
`It's a Cheshire cat,' said the Duchess, `and that's why.
Pig!'
She said the last word with such sudden violence that Alice
quite jumped; but she saw in another moment that it was addressed
to the baby, and not to her, so she took courage, and went on
again:--
`I didn't know that Cheshire cats always grinned; in fact, I
didn't know that cats COULD grin.'
`They all can,' said the Duchess; `and most of 'em do.'
`I don't know of any that do,' Alice said very politely,
feeling quite pleased to have got into a conversation.
`You don't know much,' said the Duchess; `and that's a fact.'
Alice did not at all like the tone of this remark, and thought
it would be as well to introduce some other subject of
conversation. While she was trying to fix on one, the cook took
the cauldron of soup off the fire, and at once set to work
throwing everything within her reach at the Duchess and the baby
--the fire-irons came first; then followed a shower of saucepans,
plates, and dishes. The Duchess took no notice of them even when
they hit her; and the baby was howling so much already, that it
was quite impossible to say whether the blows hurt it or not.
`Oh, PLEASE mind what you're doing!' cried Alice, jumping up
and down in an agony of terror. `Oh, there goes his PRECIOUS
nose'; as an unusually large saucepan flew close by it, and very
nearly carried it off.
`If everybody minded their own business,' the Duchess said in a
hoarse growl, `the world would go round a deal faster than it
does.'
`Which would NOT be an advantage,' said Alice, who felt very
glad to get an opportunity of showing off a little of her
knowledge. `Just think of what work it would make with the day
and night! You see the earth takes twenty-four hours to turn
round on its axis--'
`Talking of axes,' said the Duchess, `chop off her head!'
Alice glanced rather anxiously at the cook, to see if she meant
to take the hint; but the cook was busily stirring the soup, and
seemed not to be listening, so she went on again: `Twenty-four
hours, I THINK; or is it twelve? I--'
`Oh, don't bother ME,' said the Duchess; `I never could abide
figures!' And with that she began nursing her child again,
singing a sort of lullaby to it as she did so, and giving it a
violent shake at the end of every line:
`Speak roughly to your little boy,
And beat him when he sneezes:
He only does it to annoy,
Because he knows it teases.'
CHORUS.
(In which the cook and the baby joined):--
`Wow! wow! wow!'
While the Duchess sang the second verse of the song, she kept
tossing the baby violently up and down, and the poor little thing
howled so, that Alice could hardly hear the words:--
`I speak severely to my boy,
I beat him when he sneezes;
For he can thoroughly enjoy
The pepper when he pleases!'
CHORUS.
`Wow! wow! wow!'
`Here! you may nurse it a bit, if you like!' the Duchess said
to Alice, flinging the baby at her as she spoke. `I must go and
get ready to play croquet with the Queen,' and she hurried out of
the room. The cook threw a frying-pan after her as she went out,
but it just missed her.
Alice caught the baby with some difficulty, as it was a queer-
shaped little creature, and held out its arms and legs in all
directions, `just like a star-fish,' thought Alice. The poor
little thing was snorting like a steam-engine when she caught it,
and kept doubling itself up and straightening itself out again,
so that altogether, for the first minute or two, it was as much
as she could do to hold it.
As soon as she had made out the proper way of nursing it,
(which was to twist it up into a sort of knot, and then keep
tight hold of its right ear and left foot, so as to prevent its
undoing itself,) she carried it out into the open air. `IF I
don't take this child away with me,' thought Alice, `they're sure
to kill it in a day or two: wouldn't it be murder to leave it
behind?' She said the last words out loud, and the little thing
grunted in reply (it had left off sneezing by this time). `Don't
grunt,' said Alice; `that's not at all a proper way of expressing
yourself.'
The baby grunted again, and Alice looked very anxiously into
its face to see what was the matter with it. There could be no
doubt that it had a VERY turn-up nose, much more like a snout
than a real nose; also its eyes were getting extremely small for
a baby: altogether Alice did not like the look of the thing at
all. `But perhaps it was only sobbing,' she thought, and looked
into its eyes again, to see if there were any tears.
No, there were no tears. `If you're going to turn into a pig,
my dear,' said Alice, seriously, `I'll have nothing more to do
with you. Mind now!' The poor little thing sobbed again (or
grunted, it was impossible to say which), and they went on for
some while in silence.
Alice was just beginning to think to herself, `Now, what am I
to do with this creature when I get it home?' when it grunted
again, so violently, that she looked down into its face in some
alarm. This time there could be NO mistake about it: it was
neither more nor less than a pig, and she felt that it would be
quite absurd for her to carry it further.
So she set the little creature down, and felt quite relieved to
see it trot away quietly into the wood. `If it had grown up,'
she said to herself, `it would have made a dreadfully ugly child:
but it makes rather a handsome pig, I think.' And she began
thinking over other children she knew, who might do very well as
pigs, and was just saying to herself, `if one only knew the right
way to change them--' when she was a little startled by seeing
the Cheshire Cat sitting on a bough of a tree a few yards off.
The Cat only grinned when it saw Alice. It looked good-
natured, she thought: still it had VERY long claws and a great
many teeth, so she felt that it ought to be treated with respect.
`Cheshire Puss,' she began, rather timidly, as she did not at
all know whether it would like the name: however, it only
grinned a little wider. `Come, it's pleased so far,' thought
Alice, and she went on. `Would you tell me, please, which way I
ought to go from here?'
`That depends a good deal on where you want to get to,' said
the Cat.
`I don't much care where--' said Alice.
`Then it doesn't matter which way you go,' said the Cat.
`--so long as I get SOMEWHERE,' Alice added as an explanation.
`Oh, you're sure to do that,' said the Cat, `if you only walk
long enough.'
Alice felt that this could not be denied, so she tried another
question. `What sort of people live about here?'
`In THAT direction,' the Cat said, waving its right paw round,
`lives a Hatter: and in THAT direction,' waving the other paw,
`lives a March Hare. Visit either you like: they're both mad.'
`But I don't want to go among mad people,' Alice remarked.
`Oh, you can't help that,' said the Cat: `we're all mad here.
I'm mad. You're mad.'
`How do you know I'm mad?' said Alice.
`You must be,' said the Cat, `or you wouldn't have come here.'
Alice didn't think that proved it at all; however, she went on
`And how do you know that you're mad?'
`To begin with,' said the Cat, `a dog's not mad. You grant
that?'
`I suppose so,' said Alice.
`Well, then,' the Cat went on, `you see, a dog growls when it's
angry, and wags its tail when it's pleased. Now I growl when I'm
pleased, and wag my tail when I'm angry. Therefore I'm mad.'
`I call it purring, not growling,' said Alice.
`Call it what you like,' said the Cat. `Do you play croquet
with the Queen to-day?'
`I should like it very much,' said Alice, `but I haven't been
invited yet.'
`You'll see me there,' said the Cat, and vanished.
Alice was not much surprised at this, she was getting so used
to queer things happening. While she was looking at the place
where it had been, it suddenly appeared again.
`By-the-bye, what became of the baby?' said the Cat. `I'd
nearly forgotten to ask.'
`It turned into a pig,' Alice quietly said, just as if it had
come back in a natural way.
`I thought it would,' said the Cat, and vanished again.
Alice waited a little, half expecting to see it again, but it
did not appear, and after a minute or two she walked on in the
direction in which the March Hare was said to live. `I've seen
hatters before,' she said to herself; `the March Hare will be
much the most interesting, and perhaps as this is May it won't be
raving mad--at least not so mad as it was in March.' As she said
this, she looked up, and there was the Cat again, sitting on a
branch of a tree.
`Did you say pig, or fig?' said the Cat.
`I said pig,' replied Alice; `and I wish you wouldn't keep
appearing and vanishing so suddenly: you make one quite giddy.'
`All right,' said the Cat; and this time it vanished quite
slowly, beginning with the end of the tail, and ending with the
grin, which remained some time after the rest of it had gone.
`Well! I've often seen a cat without a grin,' thought Alice;
`but a grin without a cat! It's the most curious thing I ever
say in my life!'
She had not gone much farther before she came in sight of the
house of the March Hare: she thought it must be the right house,
because the chimneys were shaped like ears and the roof was
thatched with fur. It was so large a house, that she did not
like to go nearer till she had nibbled some more of the lefthand
bit of mushroom, and raised herself to about two feet high: even
then she walked up towards it rather timidly, saying to herself
`Suppose it should be raving mad after all! I almost wish I'd
gone to see the Hatter instead!'
CHAPTER VII
A Mad Tea-Party
There was a table set out under a tree in front of the house,
and the March Hare and the Hatter were having tea at it: a
Dormouse was sitting between them, fast asleep, and the other two
were using it as a cushion, resting their elbows on it, and the
talking over its head. `Very uncomfortable for the Dormouse,'
thought Alice; `only, as it's asleep, I suppose it doesn't mind.'
The table was a large one, but the three were all crowded
together at one corner of it: `No room! No room!' they cried
out when they saw Alice coming. `There's PLENTY of room!' said
Alice indignantly, and she sat down in a large arm-chair at one
end of the table.
`Have some wine,' the March Hare said in an encouraging tone.
Alice looked all round the table, but there was nothing on it
but tea. `I don't see any wine,' she remarked.
`There isn't any,' said the March Hare.
`Then it wasn't very civil of you to offer it,' said Alice
angrily.
`It wasn't very civil of you to sit down without being
invited,' said the March Hare.
`I didn't know it was YOUR table,' said Alice; `it's laid for a
great many more than three.'
`Your hair wants cutting,' said the Hatter. He had been
looking at Alice for some time with great curiosity, and this was
his first speech.
`You should learn not to make personal remarks,' Alice said
with some severity; `it's very rude.'
The Hatter opened his eyes very wide on hearing this; but all
he SAID was, `Why is a raven like a writing-desk?'
`Come, we shall have some fun now!' thought Alice. `I'm glad
they've begun asking riddles.--I believe I can guess that,' she
added aloud.
`Do you mean that you think you can find out the answer to it?'
said the March Hare.
`Exactly so,' said Alice.
`Then you should say what you mean,' the March Hare went on.
`I do,' Alice hastily replied; `at least--at least I mean what
I say--that's the same thing, you know.'
`Not the same thing a bit!' said the Hatter. `You might just
as well say that "I see what I eat" is the same thing as "I eat
what I see"!'
`You might just as well say,' added the March Hare, `that "I
like what I get" is the same thing as "I get what I like"!'
`You might just as well say,' added the Dormouse, who seemed to
be talking in his sleep, `that "I breathe when I sleep" is the
same thing as "I sleep when I breathe"!'
`It IS the same thing with you,' said the Hatter, and here the
conversation dropped, and the party sat silent for a minute,
while Alice thought over all she could remember about ravens and
writing-desks, which wasn't much.
The Hatter was the first to break the silence. `What day of
the month is it?' he said, turning to Alice: he had taken his
watch out of his pocket, and was looking at it uneasily, shaking
it every now and then, and holding it to his ear.
Alice considered a little, and then said `The fourth.'
`Two days wrong!' sighed the Hatter. `I told you butter
wouldn't suit the works!' he added looking angrily at the March
Hare.
`It was the BEST butter,' the March Hare meekly replied.
`Yes, but some crumbs must have got in as well,' the Hatter
grumbled: `you shouldn't have put it in with the bread-knife.'
The March Hare took the watch and looked at it gloomily: then
he dipped it into his cup of tea, and looked at it again: but he
could think of nothing better to say than his first remark, `It
was the BEST butter, you know.'
Alice had been looking over his shoulder with some curiosity.
`What a funny watch!' she remarked. `It tells the day of the
month, and doesn't tell what o'clock it is!'
`Why should it?' muttered the Hatter. `Does YOUR watch tell
you what year it is?'
`Of course not,' Alice replied very readily: `but that's
because it stays the same year for such a long time together.'
`Which is just the case with MINE,' said the Hatter.
Alice felt dreadfully puzzled. The Hatter's remark seemed to
have no sort of meaning in it, and yet it was certainly English.
`I don't quite understand you,' she said, as politely as she
could.
`The Dormouse is asleep again,' said the Hatter, and he poured
a little hot tea upon its nose.
The Dormouse shook its head impatiently, and said, without
opening its eyes, `Of course, of course; just what I was going to
remark myself.'
`Have you guessed the riddle yet?' the Hatter said, turning to
Alice again.
`No, I give it up,' Alice replied: `what's the answer?'
`I haven't the slightest idea,' said the Hatter.
`Nor I,' said the March Hare.
Alice sighed wearily. `I think you might do something better
with the time,' she said, `than waste it in asking riddles that
have no answers.'
`If you knew Time as well as I do,' said the Hatter, `you
wouldn't talk about wasting IT. It's HIM.'
`I don't know what you mean,' said Alice.
`Of course you don't!' the Hatter said, tossing his head
contemptuously. `I dare say you never even spoke to Time!'
`Perhaps not,' Alice cautiously replied: `but I know I have to
beat time when I learn music.'
`Ah! that accounts for it,' said the Hatter. `He won't stand
beating. Now, if you only kept on good terms with him, he'd do
almost anything you liked with the clock. For instance, suppose
it were nine o'clock in the morning, just time to begin lessons:
you'd only have to whisper a hint to Time, and round goes the
clock in a twinkling! Half-past one, time for dinner!'
(`I only wish it was,' the March Hare said to itself in a
whisper.)
`That would be grand, certainly,' said Alice thoughtfully:
`but then--I shouldn't be hungry for it, you know.'
`Not at first, perhaps,' said the Hatter: `but you could keep
it to half-past one as long as you liked.'
`Is that the way YOU manage?' Alice asked.
The Hatter shook his head mournfully. `Not I!' he replied.
`We quarrelled last March--just before HE went mad, you know--'
(pointing with his tea spoon at the March Hare,) `--it was at the
great concert given by the Queen of Hearts, and I had to sing
"Twinkle, twinkle, little bat!
How I wonder what you're at!"
You know the song, perhaps?'
`I've heard something like it,' said Alice.
`It goes on, you know,' the Hatter continued, `in this way:--
"Up above the world you fly,
Like a tea-tray in the sky.
Twinkle, twinkle--"'
Here the Dormouse shook itself, and began singing in its sleep
`Twinkle, twinkle, twinkle, twinkle--' and went on so long that
they had to pinch it to make it stop.
`Well, I'd hardly finished the first verse,' said the Hatter,
`when the Queen jumped up and bawled out, "He's murdering the
time! Off with his head!"'
`How dreadfully savage!' exclaimed Alice.
`And ever since that,' the Hatter went on in a mournful tone,
`he won't do a thing I ask! It's always six o'clock now.'
A bright idea came into Alice's head. `Is that the reason so
many tea-things are put out here?' she asked.
`Yes, that's it,' said the Hatter with a sigh: `it's always
tea-time, and we've no time to wash the things between whiles.'
`Then you keep moving round, I suppose?' said Alice.
`Exactly so,' said the Hatter: `as the things get used up.'
`But what happens when you come to the beginning again?' Alice
ventured to ask.
`Suppose we change the subject,' the March Hare interrupted,
yawning. `I'm getting tired of this. I vote the young lady
tells us a story.'
`I'm afraid I don't know one,' said Alice, rather alarmed at
the proposal.
`Then the Dormouse shall!' they both cried. `Wake up,
Dormouse!' And they pinched it on both sides at once.
The Dormouse slowly opened his eyes. `I wasn't asleep,' he
said in a hoarse, feeble voice: `I heard every word you fellows
were saying.'
`Tell us a story!' said the March Hare.
`Yes, please do!' pleaded Alice.
`And be quick about it,' added the Hatter, `or you'll be asleep
again before it's done.'
`Once upon a time there were three little sisters,' the
Dormouse began in a great hurry; `and their names were Elsie,
Lacie, and Tillie; and they lived at the bottom of a well--'
`What did they live on?' said Alice, who always took a great
interest in questions of eating and drinking.
`They lived on treacle,' said the Dormouse, after thinking a
minute or two.
`They couldn't have done that, you know,' Alice gently
remarked; `they'd have been ill.'
`So they were,' said the Dormouse; `VERY ill.'
Alice tried to fancy to herself what such an extraordinary ways
of living would be like, but it puzzled her too much, so she went
on: `But why did they live at the bottom of a well?'
`Take some more tea,' the March Hare said to Alice, very
earnestly.
`I've had nothing yet,' Alice replied in an offended tone, `so
I can't take more.'
`You mean you can't take LESS,' said the Hatter: `it's very
easy to take MORE than nothing.'
`Nobody asked YOUR opinion,' said Alice.
`Who's making personal remarks now?' the Hatter asked
triumphantly.
Alice did not quite know what to say to this: so she helped
herself to some tea and bread-and-butter, and then turned to the
Dormouse, and repeated her question. `Why did they live at the
bottom of a well?'
The Dormouse again took a minute or two to think about it, and
then said, `It was a treacle-well.'
`There's no such thing!' Alice was beginning very angrily, but
the Hatter and the March Hare went `Sh! sh!' and the Dormouse
sulkily remarked, `If you can't be civil, you'd better finish the
story for yourself.'
`No, please go on!' Alice said very humbly; `I won't interrupt
again. I dare say there may be ONE.'
`One, indeed!' said the Dormouse indignantly. However, he
consented to go on. `And so these three little sisters--they
were learning to draw, you know--'
`What did they draw?' said Alice, quite forgetting her promise.
`Treacle,' said the Dormouse, without considering at all this
time.
`I want a clean cup,' interrupted the Hatter: `let's all move
one place on.'
He moved on as he spoke, and the Dormouse followed him: the
March Hare moved into the Dormouse's place, and Alice rather
unwillingly took the place of the March Hare. The Hatter was the
only one who got any advantage from the change: and Alice was a
good deal worse off than before, as the March Hare had just upset
the milk-jug into his plate.
Alice did not wish to offend the Dormouse again, so she began
very cautiously: `But I don't understand. Where did they draw
the treacle from?'
`You can draw water out of a water-well,' said the Hatter; `so
I should think you could draw treacle out of a treacle-well--eh,
stupid?'
`But they were IN the well,' Alice said to the Dormouse, not
choosing to notice this last remark.
`Of course they were', said the Dormouse; `--well in.'
This answer so confused poor Alice, that she let the Dormouse
go on for some time without interrupting it.
`They were learning to draw,' the Dormouse went on, yawning and
rubbing its eyes, for it was getting very sleepy; `and they drew
all manner of things--everything that begins with an M--'
`Why with an M?' said Alice.
`Why not?' said the March Hare.
Alice was silent.
The Dormouse had closed its eyes by this time, and was going
off into a doze; but, on being pinched by the Hatter, it woke up
again with a little shriek, and went on: `--that begins with an
M, such as mouse-traps, and the moon, and memory, and muchness--
you know you say things are "much of a muchness"--did you ever
see such a thing as a drawing of a muchness?'
`Really, now you ask me,' said Alice, very much confused, `I
don't think--'
`Then you shouldn't talk,' said the Hatter.
This piece of rudeness was more than Alice could bear: she got
up in great disgust, and walked off; the Dormouse fell asleep
instantly, and neither of the others took the least notice of her
going, though she looked back once or twice, half hoping that
they would call after her: the last time she saw them, they were
trying to put the Dormouse into the teapot.
`At any rate I'll never go THERE again!' said Alice as she
picked her way through the wood. `It's the stupidest tea-party I
ever was at in all my life!'
Just as she said this, she noticed that one of the trees had a
door leading right into it. `That's very curious!' she thought.
`But everything's curious today. I think I may as well go in at
once.' And in she went.
Once more she found herself in the long hall, and close to the
little glass table. `Now, I'll manage better this time,' she
said to herself, and began by taking the little golden key, and
unlocking the door that led into the garden. Then she went to
work nibbling at the mushroom (she had kept a piece of it in her
pocked) till she was about a foot high: then she walked down the
little passage: and THEN--she found herself at last in the
beautiful garden, among the bright flower-beds and the cool
fountains.
CHAPTER VIII
The Queen's Croquet-Ground
A large rose-tree stood near the entrance of the garden: the
roses growing on it were white, but there were three gardeners at
it, busily painting them red. Alice thought this a very curious
thing, and she went nearer to watch them, and just as she came up
to them she heard one of them say, `Look out now, Five! Don't go
splashing paint over me like that!'
`I couldn't help it,' said Five, in a sulky tone; `Seven jogged
my elbow.'
On which Seven looked up and said, `That's right, Five! Always
lay the blame on others!'
`YOU'D better not talk!' said Five. `I heard the Queen say only
yesterday you deserved to be beheaded!'
`What for?' said the one who had spoken first.
`That's none of YOUR business, Two!' said Seven.
`Yes, it IS his business!' said Five, `and I'll tell him--it
was for bringing the cook tulip-roots instead of onions.'
Seven flung down his brush, and had just begun `Well, of all
the unjust things--' when his eye chanced to fall upon Alice, as
she stood watching them, and he checked himself suddenly: the
others looked round also, and all of them bowed low.
`Would you tell me,' said Alice, a little timidly, `why you are
painting those roses?'
Five and Seven said nothing, but looked at Two. Two began in a
low voice, `Why the fact is, you see, Miss, this here ought to
have been a RED rose-tree, and we put a white one in by mistake;
and if the Queen was to find it out, we should all have our heads
cut off, you know. So you see, Miss, we're doing our best, afore
she comes, to--' At this moment Five, who had been anxiously
looking across the garden, called out `The Queen! The Queen!'
and the three gardeners instantly threw themselves flat upon
their faces. There was a sound of many footsteps, and Alice
looked round, eager to see the Queen.
First came ten soldiers carrying clubs; these were all shaped
like the three gardeners, oblong and flat, with their hands and
feet at the corners: next the ten courtiers; these were
ornamented all over with diamonds, and walked two and two, as the
soldiers did. After these came the royal children; there were
ten of them, and the little dears came jumping merrily along hand
in hand, in couples: they were all ornamented with hearts. Next
came the guests, mostly Kings and Queens, and among them Alice
recognised the White Rabbit: it was talking in a hurried nervous
manner, smiling at everything that was said, and went by without
noticing her. Then followed the Knave of Hearts, carrying the
King's crown on a crimson velvet cushion; and, last of all this
grand procession, came THE KING AND QUEEN OF HEARTS.
Alice was rather doubtful whether she ought not to lie down on
her face like the three gardeners, but she could not remember
every having heard of such a rule at processions; `and besides,
what would be the use of a procession,' thought she, `if people
had all to lie down upon their faces, so that they couldn't see
it?' So she stood still where she was, and waited.
When the procession came opposite to Alice, they all stopped
and looked at her, and the Queen said severely `Who is this?'
She said it to the Knave of Hearts, who only bowed and smiled in
reply.
`Idiot!' said the Queen, tossing her head impatiently; and,
turning to Alice, she went on, `What's your name, child?'
`My name is Alice, so please your Majesty,' said Alice very
politely; but she added, to herself, `Why, they're only a pack of
cards, after all. I needn't be afraid of them!'
`And who are THESE?' said the Queen, pointing to the three
gardeners who were lying round the rosetree; for, you see, as
they were lying on their faces, and the pattern on their backs
was the same as the rest of the pack, she could not tell whether
they were gardeners, or soldiers, or courtiers, or three of her
own children.
`How should I know?' said Alice, surprised at her own courage.
`It's no business of MINE.'
The Queen turned crimson with fury, and, after glaring at her
for a moment like a wild beast, screamed `Off with her head!
Off--'
`Nonsense!' said Alice, very loudly and decidedly, and the
Queen was silent.
The King laid his hand upon her arm, and timidly said
`Consider, my dear: she is only a child!'
The Queen turned angrily away from him, and said to the Knave
`Turn them over!'
The Knave did so, very carefully, with one foot.
`Get up!' said the Queen, in a shrill, loud voice, and the
three gardeners instantly jumped up, and began bowing to the
King, the Queen, the royal children, and everybody else.
`Leave off that!' screamed the Queen. `You make me giddy.'
And then, turning to the rose-tree, she went on, `What HAVE you
been doing here?'
`May it please your Majesty,' said Two, in a very humble tone,
going down on one knee as he spoke, `we were trying--'
`I see!' said the Queen, who had meanwhile been examining the
roses. `Off with their heads!' and the procession moved on,
three of the soldiers remaining behind to execute the unfortunate
gardeners, who ran to Alice for protection.
`You shan't be beheaded!' said Alice, and she put them into a
large flower-pot that stood near. The three soldiers wandered
about for a minute or two, looking for them, and then quietly
marched off after the others.
`Are their heads off?' shouted the Queen.
`Their heads are gone, if it please your Majesty!' the soldiers
shouted in reply.
`That's right!' shouted the Queen. `Can you play croquet?'
The soldiers were silent, and looked at Alice, as the question
was evidently meant for her.
`Yes!' shouted Alice.
`Come on, then!' roared the Queen, and Alice joined the
procession, wondering very much what would happen next.
`It's--it's a very fine day!' said a timid voice at her side.
She was walking by the White Rabbit, who was peeping anxiously
into her face.
`Very,' said Alice: `--where's the Duchess?'
`Hush! Hush!' said the Rabbit in a low, hurried tone. He
looked anxiously over his shoulder as he spoke, and then raised
himself upon tiptoe, put his mouth close to her ear, and
whispered `She's under sentence of execution.'
`What for?' said Alice.
`Did you say "What a pity!"?' the Rabbit asked.
`No, I didn't,' said Alice: `I don't think it's at all a pity.
I said "What for?"'
`She boxed the Queen's ears--' the Rabbit began. Alice gave a
little scream of laughter. `Oh, hush!' the Rabbit whispered in a
frightened tone. `The Queen will hear you! You see, she came
rather late, and the Queen said--'
`Get to your places!' shouted the Queen in a voice of thunder,
and people began running about in all directions, tumbling up
against each other; however, they got settled down in a minute or
two, and the game began. Alice thought she had never seen such a
curious croquet-ground in her life; it was all ridges and
furrows; the balls were live hedgehogs, the mallets live
flamingoes, and the soldiers had to double themselves up and to
stand on their hands and feet, to make the arches.
The chief difficulty Alice found at first was in managing her
flamingo: she succeeded in getting its body tucked away,
comfortably enough, under her arm, with its legs hanging down,
but generally, just as she had got its neck nicely straightened
out, and was going to give the hedgehog a blow with its head, it
WOULD twist itself round and look up in her face, with such a
puzzled expression that she could not help bursting out laughing:
and when she had got its head down, and was going to begin again,
it was very provoking to find that the hedgehog had unrolled
itself, and was in the act of crawling away: besides all this,
there was generally a ridge or furrow in the way wherever she
wanted to send the hedgehog to, and, as the doubled-up soldiers
were always getting up and walking off to other parts of the
ground, Alice soon came to the conclusion that it was a very
difficult game indeed.
The players all played at once without waiting for turns,
quarrelling all the while, and fighting for the hedgehogs; and in
a very short time the Queen was in a furious passion, and went
stamping about, and shouting `Off with his head!' or `Off with
her head!' about once in a minute.
Alice began to feel very uneasy: to be sure, she had not as
yet had any dispute with the Queen, but she knew that it might
happen any minute, `and then,' thought she, `what would become of
me? They're dreadfully fond of beheading people here; the great
wonder is, that there's any one left alive!'
She was looking about for some way of escape, and wondering
whether she could get away without being seen, when she noticed a
curious appearance in the air: it puzzled her very much at
first, but, after watching it a minute or two, she made it out to
be a grin, and she said to herself `It's the Cheshire Cat: now I
shall have somebody to talk to.'
`How are you getting on?' said the Cat, as soon as there was
mouth enough for it to speak with.
Alice waited till the eyes appeared, and then nodded. `It's no
use speaking to it,' she thought, `till its ears have come, or at
least one of them.' In another minute the whole head appeared,
and then Alice put down her flamingo, and began an account of the
game, feeling very glad she had someone to listen to her. The
Cat seemed to think that there was enough of it now in sight, and
no more of it appeared.
`I don't think they play at all fairly,' Alice began, in rather
a complaining tone, `and they all quarrel so dreadfully one can't
hear oneself speak--and they don't seem to have any rules in
particular; at least, if there are, nobody attends to them--and
you've no idea how confusing it is all the things being alive;
for instance, there's the arch I've got to go through next
walking about at the other end of the ground--and I should have
croqueted the Queen's hedgehog just now, only it ran away when it
saw mine coming!'
`How do you like the Queen?' said the Cat in a low voice.
`Not at all,' said Alice: `she's so extremely--' Just then
she noticed that the Queen was close behind her, listening: so
she went on, `--likely to win, that it's hardly worth while
finishing the game.'
The Queen smiled and passed on.
`Who ARE you talking to?' said the King, going up to Alice, and
looking at the Cat's head with great curiosity.
`It's a friend of mine--a Cheshire Cat,' said Alice: `allow me
to introduce it.'
`I don't like the look of it at all,' said the King: `however,
it may kiss my hand if it likes.'
`I'd rather not,' the Cat remarked.
`Don't be impertinent,' said the King, `and don't look at me
like that!' He got behind Alice as he spoke.
`A cat may look at a king,' said Alice. `I've read that in
some book, but I don't remember where.'
`Well, it must be removed,' said the King very decidedly, and
he called the Queen, who was passing at the moment, `My dear! I
wish you would have this cat removed!'
The Queen had only one way of settling all difficulties, great
or small. `Off with his head!' she said, without even looking
round.
`I'll fetch the executioner myself,' said the King eagerly, and
he hurried off.
Alice thought she might as well go back, and see how the game
was going on, as she heard the Queen's voice in the distance,
screaming with passion. She had already heard her sentence three
of the players to be executed for having missed their turns, and
she did not like the look of things at all, as the game was in
such confusion that she never knew whether it was her turn or
not. So she went in search of her hedgehog.
The hedgehog was engaged in a fight with another hedgehog,
which seemed to Alice an excellent opportunity for croqueting one
of them with the other: the only difficulty was, that her
flamingo was gone across to the other side of the garden, where
Alice could see it trying in a helpless sort of way to fly up
into a tree.
By the time she had caught the flamingo and brought it back,
the fight was over, and both the hedgehogs were out of sight:
`but it doesn't matter much,' thought Alice, `as all the arches
are gone from this side of the ground.' So she tucked it away
under her arm, that it might not escape again, and went back for
a little more conversation with her friend.
When she got back to the Cheshire Cat, she was surprised to
find quite a large crowd collected round it: there was a dispute
going on between the executioner, the King, and the Queen, who
were all talking at once, while all the rest were quite silent,
and looked very uncomfortable.
The moment Alice appeared, she was appealed to by all three to
settle the question, and they repeated their arguments to her,
though, as they all spoke at once, she found it very hard indeed
to make out exactly what they said.
The executioner's argument was, that you couldn't cut off a
head unless there was a body to cut it off from: that he had
never had to do such a thing before, and he wasn't going to begin
at HIS time of life.
The King's argument was, that anything that had a head could be
beheaded, and that you weren't to talk nonsense.
The Queen's argument was, that if something wasn't done about
it in less than no time she'd have everybody executed, all round.
(It was this last remark that had made the whole party look so
grave and anxious.)
Alice could think of nothing else to say but `It belongs to the
Duchess: you'd better ask HER about it.'
`She's in prison,' the Queen said to the executioner: `fetch
her here.' And the executioner went off like an arrow.
The Cat's head began fading away the moment he was gone, and,
by the time he had come back with the Dutchess, it had entirely
disappeared; so the King and the executioner ran wildly up and
down looking for it, while the rest of the party went back to the game.
CHAPTER IX
The Mock Turtle's Story
`You can't think how glad I am to see you again, you dear old
thing!' said the Duchess, as she tucked her arm affectionately
into Alice's, and they walked off together.
Alice was very glad to find her in such a pleasant temper, and
thought to herself that perhaps it was only the pepper that had
made her so savage when they met in the kitchen.
`When I'M a Duchess,' she said to herself, (not in a very
hopeful tone though), `I won't have any pepper in my kitchen AT
ALL. Soup does very well without--Maybe it's always pepper that
makes people hot-tempered,' she went on, very much pleased at
having found out a new kind of rule, `and vinegar that makes them
sour--and camomile that makes them bitter--and--and barley-sugar
and such things that make children sweet-tempered. I only wish
people knew that: then they wouldn't be so stingy about it, you
know--'
She had quite forgotten the Duchess by this time, and was a
little startled when she heard her voice close to her ear.
`You're thinking about something, my dear, and that makes you
forget to talk. I can't tell you just now what the moral of that
is, but I shall remember it in a bit.'
`Perhaps it hasn't one,' Alice ventured to remark.
`Tut, tut, child!' said the Duchess. `Everything's got a
moral, if only you can find it.' And she squeezed herself up
closer to Alice's side as she spoke.
Alice did not much like keeping so close to her: first,
because the Duchess was VERY ugly; and secondly, because she was
exactly the right height to rest her chin upon Alice's shoulder,
and it was an uncomfortably sharp chin. However, she did not
like to be rude, so she bore it as well as she could.
`The game's going on rather better now,' she said, by way of
keeping up the conversation a little.
`'Tis so,' said the Duchess: `and the moral of that is--"Oh,
'tis love, 'tis love, that makes the world go round!"'
`Somebody said,' Alice whispered, `that it's done by everybody
minding their own business!'
`Ah, well! It means much the same thing,' said the Duchess,
digging her sharp little chin into Alice's shoulder as she added,
`and the moral of THAT is--"Take care of the sense, and the
sounds will take care of themselves."'
`How fond she is of finding morals in things!' Alice thought to
herself.
`I dare say you're wondering why I don't put my arm round your
waist,' the Duchess said after a pause: `the reason is, that I'm
doubtful about the temper of your flamingo. Shall I try the
experiment?'
`HE might bite,' Alice cautiously replied, not feeling at all
anxious to have the experiment tried.
`Very true,' said the Duchess: `flamingoes and mustard both
bite. And the moral of that is--"Birds of a feather flock
together."'
`Only mustard isn't a bird,' Alice remarked.
`Right, as usual,' said the Duchess: `what a clear way you
have of putting things!'
`It's a mineral, I THINK,' said Alice.
`Of course it is,' said the Duchess, who seemed ready to agree
to everything that Alice said; `there's a large mustard-mine near
here. And the moral of that is--"The more there is of mine, the
less there is of yours."'
`Oh, I know!' exclaimed Alice, who had not attended to this
last remark, `it's a vegetable. It doesn't look like one, but it
is.'
`I quite agree with you,' said the Duchess; `and the moral of
that is--"Be what you would seem to be"--or if you'd like it put
more simply--"Never imagine yourself not to be otherwise than
what it might appear to others that what you were or might have
been was not otherwise than what you had been would have appeared
to them to be otherwise."'
`I think I should understand that better,' Alice said very
politely, `if I had it written down: but I can't quite follow it
as you say it.'
`That's nothing to what I could say if I chose,' the Duchess
replied, in a pleased tone.
`Pray don't trouble yourself to say it any longer than that,'
said Alice.
`Oh, don't talk about trouble!' said the Duchess. `I make you
a present of everything I've said as yet.'
`A cheap sort of present!' thought Alice. `I'm glad they don't
give birthday presents like that!' But she did not venture to
say it out loud.
`Thinking again?' the Duchess asked, with another dig of her
sharp little chin.
`I've a right to think,' said Alice sharply, for she was
beginning to feel a little worried.
`Just about as much right,' said the Duchess, `as pigs have to
fly; and the m--'
But here, to Alice's great surprise, the Duchess's voice died
away, even in the middle of her favourite word `moral,' and the
arm that was linked into hers began to tremble. Alice looked up,
and there stood the Queen in front of them, with her arms folded,
frowning like a thunderstorm.
`A fine day, your Majesty!' the Duchess began in a low, weak
voice.
`Now, I give you fair warning,' shouted the Queen, stamping on
the ground as she spoke; `either you or your head must be off,
and that in about half no time! Take your choice!'
The Duchess took her choice, and was gone in a moment.
`Let's go on with the game,' the Queen said to Alice; and Alice
was too much frightened to say a word, but slowly followed her
back to the croquet-ground.
The other guests had taken advantage of the Queen's absence,
and were resting in the shade: however, the moment they saw her,
they hurried back to the game, the Queen merely remarking that a
moment's delay would cost them their lives.
All the time they were playing the Queen never left off
quarrelling with the other players, and shouting `Off with his
head!' or `Off with her head!' Those whom she sentenced were
taken into custody by the soldiers, who of course had to leave
off being arches to do this, so that by the end of half an hour
or so there were no arches left, and all the players, except the
King, the Queen, and Alice, were in custody and under sentence of
execution.
Then the Queen left off, quite out of breath, and said to
Alice, `Have you seen the Mock Turtle yet?'
`No,' said Alice. `I don't even know what a Mock Turtle is.'
`It's the thing Mock Turtle Soup is made from,' said the Queen.
`I never saw one, or heard of one,' said Alice.
`Come on, then,' said the Queen, `and he shall tell you his
history,'
As they walked off together, Alice heard the King say in a low
voice, to the company generally, `You are all pardoned.' `Come,
THAT'S a good thing!' she said to herself, for she had felt quite
unhappy at the number of executions the Queen had ordered.
They very soon came upon a Gryphon, lying fast asleep in the
sun. (IF you don't know what a Gryphon is, look at the picture.)
`Up, lazy thing!' said the Queen, `and take this young lady to
see the Mock Turtle, and to hear his history. I must go back and
see after some executions I have ordered'; and she walked off,
leaving Alice alone with the Gryphon. Alice did not quite like
the look of the creature, but on the whole she thought it would
be quite as safe to stay with it as to go after that savage
Queen: so she waited.
The Gryphon sat up and rubbed its eyes: then it watched the
Queen till she was out of sight: then it chuckled. `What fun!'
said the Gryphon, half to itself, half to Alice.
`What IS the fun?' said Alice.
`Why, SHE,' said the Gryphon. `It's all her fancy, that: they
never executes nobody, you know. Come on!'
`Everybody says "come on!" here,' thought Alice, as she went
slowly after it: `I never was so ordered about in all my life,
never!'
They had not gone far before they saw the Mock Turtle in the
distance, sitting sad and lonely on a little ledge of rock, and,
as they came nearer, Alice could hear him sighing as if his heart
would break. She pitied him deeply. `What is his sorrow?' she
asked the Gryphon, and the Gryphon answered, very nearly in the
same words as before, `It's all his fancy, that: he hasn't got
no sorrow, you know. Come on!'
So they went up to the Mock Turtle, who looked at them with
large eyes full of tears, but said nothing.
`This here young lady,' said the Gryphon, `she wants for to
know your history, she do.'
`I'll tell it her,' said the Mock Turtle in a deep, hollow
tone: `sit down, both of you, and don't speak a word till I've
finished.'
So they sat down, and nobody spoke for some minutes. Alice
thought to herself, `I don't see how he can EVEN finish, if he
doesn't begin.' But she waited patiently.
`Once,' said the Mock Turtle at last, with a deep sigh, `I was
a real Turtle.'
These words were followed by a very long silence, broken only
by an occasional exclamation of `Hjckrrh!' from the Gryphon, and
the constant heavy sobbing of the Mock Turtle. Alice was very
nearly getting up and saying, `Thank you, sir, for your
interesting story,' but she could not help thinking there MUST be
more to come, so she sat still and said nothing.
`When we were little,' the Mock Turtle went on at last, more
calmly, though still sobbing a little now and then, `we went to
school in the sea. The master was an old Turtle--we used to call
him Tortoise--'
`Why did you call him Tortoise, if he wasn't one?' Alice asked.
`We called him Tortoise because he taught us,' said the Mock
Turtle angrily: `really you are very dull!'
`You ought to be ashamed of yourself for asking such a simple
question,' added the Gryphon; and then they both sat silent and
looked at poor Alice, who felt ready to sink into the earth. At
last the Gryphon said to the Mock Turtle, `Drive on, old fellow!
Don't be all day about it!' and he went on in these words:
`Yes, we went to school in the sea, though you mayn't believe
it--'
`I never said I didn't!' interrupted Alice.
`You did,' said the Mock Turtle.
`Hold your tongue!' added the Gryphon, before Alice could speak
again. The Mock Turtle went on.
`We had the best of educations--in fact, we went to school
every day--'
`I'VE been to a day-school, too,' said Alice; `you needn't be
so proud as all that.'
`With extras?' asked the Mock Turtle a little anxiously.
`Yes,' said Alice, `we learned French and music.'
`And washing?' said the Mock Turtle.
`Certainly not!' said Alice indignantly.
`Ah! then yours wasn't a really good school,' said the Mock
Turtle in a tone of great relief. `Now at OURS they had at the
end of the bill, "French, music, AND WASHING--extra."'
`You couldn't have wanted it much,' said Alice; `living at the
bottom of the sea.'
`I couldn't afford to learn it.' said the Mock Turtle with a
sigh. `I only took the regular course.'
`What was that?' inquired Alice.
`Reeling and Writhing, of course, to begin with,' the Mock
Turtle replied; `and then the different branches of Arithmetic--
Ambition, Distraction, Uglification, and Derision.'
`I never heard of "Uglification,"' Alice ventured to say. `What
is it?'
The Gryphon lifted up both its paws in surprise. `What! Never
heard of uglifying!' it exclaimed. `You know what to beautify
is, I suppose?'
`Yes,' said Alice doubtfully: `it means--to--make--anything--
prettier.'
`Well, then,' the Gryphon went on, `if you don't know what to
uglify is, you ARE a simpleton.'
Alice did not feel encouraged to ask any more questions about
it, so she turned to the Mock Turtle, and said `What else had you
to learn?'
`Well, there was Mystery,' the Mock Turtle replied, counting
off the subjects on his flappers, `--Mystery, ancient and modern,
with Seaography: then Drawling--the Drawling-master was an old
conger-eel, that used to come once a week: HE taught us
Drawling, Stretching, and Fainting in Coils.'
`What was THAT like?' said Alice.
`Well, I can't show it you myself,' the Mock Turtle said: `I'm
too stiff. And the Gryphon never learnt it.'
`Hadn't time,' said the Gryphon: `I went to the Classics
master, though. He was an old crab, HE was.'
`I never went to him,' the Mock Turtle said with a sigh: `he
taught Laughing and Grief, they used to say.'
`So he did, so he did,' said the Gryphon, sighing in his turn;
and both creatures hid their faces in their paws.
`And how many hours a day did you do lessons?' said Alice, in a
hurry to change the subject.
`Ten hours the first day,' said the Mock Turtle: `nine the
next, and so on.'
`What a curious plan!' exclaimed Alice.
`That's the reason they're called lessons,' the Gryphon
remarked: `because they lessen from day to day.'
This was quite a new idea to Alice, and she thought it over a
little before she made her next remark. `Then the eleventh day
must have been a holiday?'
`Of course it was,' said the Mock Turtle.
`And how did you manage on the twelfth?' Alice went on eagerly.
`That's enough about lessons,' the Gryphon interrupted in a
very decided tone: `tell her something about the games now.'
CHAPTER X
The Lobster Quadrille
The Mock Turtle sighed deeply, and drew the back of one flapper
across his eyes. He looked at Alice, and tried to speak, but for
a minute or two sobs choked his voice. `Same as if he had a bone
in his throat,' said the Gryphon: and it set to work shaking him
and punching him in the back. At last the Mock Turtle recovered
his voice, and, with tears running down his cheeks, he went on
again:--
`You may not have lived much under the sea--' (`I haven't,'
said Alice)--`and perhaps you were never even introduced to a lobster--'
(Alice began to say `I once tasted--' but checked herself hastily,
and said `No, never') `--so you can have no idea what a delightful
thing a Lobster Quadrille is!'
`No, indeed,' said Alice. `What sort of a dance is it?'
`Why,' said the Gryphon, `you first form into a line along the
sea-shore--'
`Two lines!' cried the Mock Turtle. `Seals, turtles, salmon,
and so on; then, when you've cleared all the jelly-fish out of
the way--'
`THAT generally takes some time,' interrupted the Gryphon.
`--you advance twice--'
`Each with a lobster as a partner!' cried the Gryphon.
`Of course,' the Mock Turtle said: `advance twice, set to
partners--'
`--change lobsters, and retire in same order,' continued the
Gryphon.
`Then, you know,' the Mock Turtle went on, `you throw the--'
`The lobsters!' shouted the Gryphon, with a bound into the air.
`--as far out to sea as you can--'
`Swim after them!' screamed the Gryphon.
`Turn a somersault in the sea!' cried the Mock Turtle,
capering wildly about.
`Back to land again, and that's all the first figure,' said the
Mock Turtle, suddenly dropping his voice; and the two creatures,
who had been jumping about like mad things all this time, sat
down again very sadly and quietly, and looked at Alice.
`It must be a very pretty dance,' said Alice timidly.
`Would you like to see a little of it?' said the Mock Turtle.
`Very much indeed,' said Alice.
`Come, let's try the first figure!' said the Mock Turtle to the
Gryphon. `We can do without lobsters, you know. Which shall
sing?'
`Oh, YOU sing,' said the Gryphon. `I've forgotten the words.'
So they began solemnly dancing round and round Alice, every now
and then treading on her toes when they passed too close, and
waving their forepaws to mark the time, while the Mock Turtle
sang this, very slowly and sadly:--
`"Will you walk a little faster?" said a whiting to a snail.
"There's a porpoise close behind us, and he's treading on my
tail.
See how eagerly the lobsters and the turtles all advance!
They are waiting on the shingle--will you come and join the
dance?
Will you, won't you, will you, won't you, will you join the
dance?
Will you, won't you, will you, won't you, won't you join the
dance?
"You can really have no notion how delightful it will be
When they take us up and throw us, with the lobsters, out to
sea!"
But the snail replied "Too far, too far!" and gave a look
askance--
Said he thanked the whiting kindly, but he would not join the
dance.
Would not, could not, would not, could not, would not join
the dance.
Would not, could not, would not, could not, could not join
the dance.
`"What matters it how far we go?" his scaly friend replied.
"There is another shore, you know, upon the other side.
The further off from England the nearer is to France--
Then turn not pale, beloved snail, but come and join the dance.
Will you, won't you, will you, won't you, will you join the
dance?
Will you, won't you, will you, won't you, won't you join the
dance?"'
`Thank you, it's a very interesting dance to watch,' said
Alice, feeling very glad that it was over at last: `and I do so
like that curious song about the whiting!'
`Oh, as to the whiting,' said the Mock Turtle, `they--you've
seen them, of course?'
`Yes,' said Alice, `I've often seen them at dinn--' she
checked herself hastily.
`I don't know where Dinn may be,' said the Mock Turtle, `but
if you've seen them so often, of course you know what they're
like.'
`I believe so,' Alice replied thoughtfully. `They have their
tails in their mouths--and they're all over crumbs.'
`You're wrong about the crumbs,' said the Mock Turtle:
`crumbs would all wash off in the sea. But they HAVE their tails
in their mouths; and the reason is--' here the Mock Turtle
yawned and shut his eyes.--`Tell her about the reason and all
that,' he said to the Gryphon.
`The reason is,' said the Gryphon, `that they WOULD go with
the lobsters to the dance. So they got thrown out to sea. So
they had to fall a long way. So they got their tails fast in
their mouths. So they couldn't get them out again. That's all.'
`Thank you,' said Alice, `it's very interesting. I never knew
so much about a whiting before.'
`I can tell you more than that, if you like,' said the
Gryphon. `Do you know why it's called a whiting?'
`I never thought about it,' said Alice. `Why?'
`IT DOES THE BOOTS AND SHOES.' the Gryphon replied very
solemnly.
Alice was thoroughly puzzled. `Does the boots and shoes!' she
repeated in a wondering tone.
`Why, what are YOUR shoes done with?' said the Gryphon. `I
mean, what makes them so shiny?'
Alice looked down at them, and considered a little before she
gave her answer. `They're done with blacking, I believe.'
`Boots and shoes under the sea,' the Gryphon went on in a deep
voice, `are done with a whiting. Now you know.'
`And what are they made of?' Alice asked in a tone of great
curiosity.
`Soles and eels, of course,' the Gryphon replied rather
impatiently: `any shrimp could have told you that.'
`If I'd been the whiting,' said Alice, whose thoughts were
still running on the song, `I'd have said to the porpoise, "Keep
back, please: we don't want YOU with us!"'
`They were obliged to have him with them,' the Mock Turtle
said: `no wise fish would go anywhere without a porpoise.'
`Wouldn't it really?' said Alice in a tone of great surprise.
`Of course not,' said the Mock Turtle: `why, if a fish came
to ME, and told me he was going a journey, I should say "With
what porpoise?"'
`Don't you mean "purpose"?' said Alice.
`I mean what I say,' the Mock Turtle replied in an offended
tone. And the Gryphon added `Come, let's hear some of YOUR
adventures.'
`I could tell you my adventures--beginning from this morning,'
said Alice a little timidly: `but it's no use going back to
yesterday, because I was a different person then.'
`Explain all that,' said the Mock Turtle.
`No, no! The adventures first,' said the Gryphon in an
impatient tone: `explanations take such a dreadful time.'
So Alice began telling them her adventures from the time when
she first saw the White Rabbit. She was a little nervous about
it just at first, the two creatures got so close to her, one on
each side, and opened their eyes and mouths so VERY wide, but she
gained courage as she went on. Her listeners were perfectly
quiet till she got to the part about her repeating `YOU ARE OLD,
FATHER WILLIAM,' to the Caterpillar, and the words all coming
different, and then the Mock Turtle drew a long breath, and said
`That's very curious.'
`It's all about as curious as it can be,' said the Gryphon.
`It all came different!' the Mock Turtle repeated
thoughtfully. `I should like to hear her try and repeat
something now. Tell her to begin.' He looked at the Gryphon as
if he thought it had some kind of authority over Alice.
`Stand up and repeat "'TIS THE VOICE OF THE SLUGGARD,"' said
the Gryphon.
`How the creatures order one about, and make one repeat
lessons!' thought Alice; `I might as well be at school at once.'
However, she got up, and began to repeat it, but her head was so
full of the Lobster Quadrille, that she hardly knew what she was
saying, and the words came very queer indeed:--
`'Tis the voice of the Lobster; I heard him declare,
"You have baked me too brown, I must sugar my hair."
As a duck with its eyelids, so he with his nose
Trims his belt and his buttons, and turns out his toes.'
[later editions continued as follows
When the sands are all dry, he is gay as a lark,
And will talk in contemptuous tones of the Shark,
But, when the tide rises and sharks are around,
His voice has a timid and tremulous sound.]
`That's different from what I used to say when I was a child,'
said the Gryphon.
`Well, I never heard it before,' said the Mock Turtle; `but it
sounds uncommon nonsense.'
Alice said nothing; she had sat down with her face in her
hands, wondering if anything would EVER happen in a natural way
again.
`I should like to have it explained,' said the Mock Turtle.
`She can't explain it,' said the Gryphon hastily. `Go on with
the next verse.'
`But about his toes?' the Mock Turtle persisted. `How COULD
he turn them out with his nose, you know?'
`It's the first position in dancing.' Alice said; but was
dreadfully puzzled by the whole thing, and longed to change the
subject.
`Go on with the next verse,' the Gryphon repeated impatiently:
`it begins "I passed by his garden."'
Alice did not dare to disobey, though she felt sure it would
all come wrong, and she went on in a trembling voice:--
`I passed by his garden, and marked, with one eye,
How the Owl and the Panther were sharing a pie--'
[later editions continued as follows
The Panther took pie-crust, and gravy, and meat,
While the Owl had the dish as its share of the treat.
When the pie was all finished, the Owl, as a boon,
Was kindly permitted to pocket the spoon:
While the Panther received knife and fork with a growl,
And concluded the banquet--]
`What IS the use of repeating all that stuff,' the Mock Turtle
interrupted, `if you don't explain it as you go on? It's by far
the most confusing thing I ever heard!'
`Yes, I think you'd better leave off,' said the Gryphon: and
Alice was only too glad to do so.
`Shall we try another figure of the Lobster Quadrille?' the
Gryphon went on. `Or would you like the Mock Turtle to sing you
a song?'
`Oh, a song, please, if the Mock Turtle would be so kind,'
Alice replied, so eagerly that the Gryphon said, in a rather
offended tone, `Hm! No accounting for tastes! Sing her "Turtle
Soup," will you, old fellow?'
The Mock Turtle sighed deeply, and began, in a voice sometimes
choked with sobs, to sing this:--
`Beautiful Soup, so rich and green,
Waiting in a hot tureen!
Who for such dainties would not stoop?
Soup of the evening, beautiful Soup!
Soup of the evening, beautiful Soup!
Beau--ootiful Soo--oop!
Beau--ootiful Soo--oop!
Soo--oop of the e--e--evening,
Beautiful, beautiful Soup!
`Beautiful Soup! Who cares for fish,
Game, or any other dish?
Who would not give all else for two p
ennyworth only of beautiful Soup?
Pennyworth only of beautiful Soup?
Beau--ootiful Soo--oop!
Beau--ootiful Soo--oop!
Soo--oop of the e--e--evening,
Beautiful, beauti--FUL SOUP!'
`Chorus again!' cried the Gryphon, and the Mock Turtle had
just begun to repeat it, when a cry of `The trial's beginning!'
was heard in the distance.
`Come on!' cried the Gryphon, and, taking Alice by the hand,
it hurried off, without waiting for the end of the song.
`What trial is it?' Alice panted as she ran; but the Gryphon
only answered `Come on!' and ran the faster, while more and more
faintly came, carried on the breeze that followed them, the
melancholy words:--
`Soo--oop of the e--e--evening,
Beautiful, beautiful Soup!'
CHAPTER XI
Who Stole the Tarts?
The King and Queen of Hearts were seated on their throne when
they arrived, with a great crowd assembled about them--all sorts
of little birds and beasts, as well as the whole pack of cards:
the Knave was standing before them, in chains, with a soldier on
each side to guard him; and near the King was the White Rabbit,
with a trumpet in one hand, and a scroll of parchment in the
other. In the very middle of the court was a table, with a large
dish of tarts upon it: they looked so good, that it made Alice
quite hungry to look at them--`I wish they'd get the trial done,'
she thought, `and hand round the refreshments!' But there seemed
to be no chance of this, so she began looking at everything about
her, to pass away the time.
Alice had never been in a court of justice before, but she had
read about them in books, and she was quite pleased to find that
she knew the name of nearly everything there. `That's the
judge,' she said to herself, `because of his great wig.'
The judge, by the way, was the King; and as he wore his crown
over the wig, (look at the frontispiece if you want to see how he
did it,) he did not look at all comfortable, and it was certainly
not becoming.
`And that's the jury-box,' thought Alice, `and those twelve
creatures,' (she was obliged to say `creatures,' you see, because
some of them were animals, and some were birds,) `I suppose they
are the jurors.' She said this last word two or three times over
to herself, being rather proud of it: for she thought, and
rightly too, that very few little girls of her age knew the
meaning of it at all. However, `jury-men' would have done just
as well.
The twelve jurors were all writing very busily on slates.
`What are they doing?' Alice whispered to the Gryphon. `They
can't have anything to put down yet, before the trial's begun.'
`They're putting down their names,' the Gryphon whispered in
reply, `for fear they should forget them before the end of the
trial.'
`Stupid things!' Alice began in a loud, indignant voice, but
she stopped hastily, for the White Rabbit cried out, `Silence in
the court!' and the King put on his spectacles and looked
anxiously round, to make out who was talking.
Alice could see, as well as if she were looking over their
shoulders, that all the jurors were writing down `stupid things!'
on their slates, and she could even make out that one of them
didn't know how to spell `stupid,' and that he had to ask his
neighbour to tell him. `A nice muddle their slates'll be in
before the trial's over!' thought Alice.
One of the jurors had a pencil that squeaked. This of course,
Alice could not stand, and she went round the court and got
behind him, and very soon found an opportunity of taking it
away. She did it so quickly that the poor little juror (it was
Bill, the Lizard) could not make out at all what had become of
it; so, after hunting all about for it, he was obliged to write
with one finger for the rest of the day; and this was of very
little use, as it left no mark on the slate.
`Herald, read the accusation!' said the King.
On this the White Rabbit blew three blasts on the trumpet, and
then unrolled the parchment scroll, and read as follows:--
`The Queen of Hearts, she made some tarts,
All on a summer day:
The Knave of Hearts, he stole those tarts,
And took them quite away!'
`Consider your verdict,' the King said to the jury.
`Not yet, not yet!' the Rabbit hastily interrupted. `There's
a great deal to come before that!'
`Call the first witness,' said the King; and the White Rabbit
blew three blasts on the trumpet, and called out, `First
witness!'
The first witness was the Hatter. He came in with a teacup in
one hand and a piece of bread-and-butter in the other. `I beg
pardon, your Majesty,' he began, `for bringing these in: but I
hadn't quite finished my tea when I was sent for.'
`You ought to have finished,' said the King. `When did you
begin?'
The Hatter looked at the March Hare, who had followed him into
the court, arm-in-arm with the Dormouse. `Fourteenth of March, I
think it was,' he said.
`Fifteenth,' said the March Hare.
`Sixteenth,' added the Dormouse.
`Write that down,' the King said to the jury, and the jury
eagerly wrote down all three dates on their slates, and then
added them up, and reduced the answer to shillings and pence.
`Take off your hat,' the King said to the Hatter.
`It isn't mine,' said the Hatter.
`Stolen!' the King exclaimed, turning to the jury, who
instantly made a memorandum of the fact.
`I keep them to sell,' the Hatter added as an explanation;
`I've none of my own. I'm a hatter.'
Here the Queen put on her spectacles, and began staring at the
Hatter, who turned pale and fidgeted.
`Give your evidence,' said the King; `and don't be nervous, or
I'll have you executed on the spot.'
This did not seem to encourage the witness at all: he kept
shifting from one foot to the other, looking uneasily at the
Queen, and in his confusion he bit a large piece out of his
teacup instead of the bread-and-butter.
Just at this moment Alice felt a very curious sensation, which
puzzled her a good deal until she made out what it was: she was
beginning to grow larger again, and she thought at first she
would get up and leave the court; but on second thoughts she
decided to remain where she was as long as there was room for
her.
`I wish you wouldn't squeeze so.' said the Dormouse, who was
sitting next to her. `I can hardly breathe.'
`I can't help it,' said Alice very meekly: `I'm growing.'
`You've no right to grow here,' said the Dormouse.
`Don't talk nonsense,' said Alice more boldly: `you know
you're growing too.'
`Yes, but I grow at a reasonable pace,' said the Dormouse:
`not in that ridiculous fashion.' And he got up very sulkily
and crossed over to the other side of the court.
All this time the Queen had never left off staring at the
Hatter, and, just as the Dormouse crossed the court, she said to
one of the officers of the court, `Bring me the list of the
singers in the last concert!' on which the wretched Hatter
trembled so, that he shook both his shoes off.
`Give your evidence,' the King repeated angrily, `or I'll have
you executed, whether you're nervous or not.'
`I'm a poor man, your Majesty,' the Hatter began, in a
trembling voice, `--and I hadn't begun my tea--not above a week
or so--and what with the bread-and-butter getting so thin--and
the twinkling of the tea--'
`The twinkling of the what?' said the King.
`It began with the tea,' the Hatter replied.
`Of course twinkling begins with a T!' said the King sharply.
`Do you take me for a dunce? Go on!'
`I'm a poor man,' the Hatter went on, `and most things
twinkled after that--only the March Hare said--'
`I didn't!' the March Hare interrupted in a great hurry.
`You did!' said the Hatter.
`I deny it!' said the March Hare.
`He denies it,' said the King: `leave out that part.'
`Well, at any rate, the Dormouse said--' the Hatter went on,
looking anxiously round to see if he would deny it too: but the
Dormouse denied nothing, being fast asleep.
`After that,' continued the Hatter, `I cut some more bread-
and-butter--'
`But what did the Dormouse say?' one of the jury asked.
`That I can't remember,' said the Hatter.
`You MUST remember,' remarked the King, `or I'll have you
executed.'
The miserable Hatter dropped his teacup and bread-and-butter,
and went down on one knee. `I'm a poor man, your Majesty,' he
began.
`You're a very poor speaker,' said the King.
Here one of the guinea-pigs cheered, and was immediately
suppressed by the officers of the court. (As that is rather a
hard word, I will just explain to you how it was done. They had
a large canvas bag, which tied up at the mouth with strings:
into this they slipped the guinea-pig, head first, and then sat
upon it.)
`I'm glad I've seen that done,' thought Alice. `I've so often
read in the newspapers, at the end of trials, "There was some
attempts at applause, which was immediately suppressed by the
officers of the court," and I never understood what it meant
till now.'
`If that's all you know about it, you may stand down,'
continued the King.
`I can't go no lower,' said the Hatter: `I'm on the floor, as
it is.'
`Then you may SIT down,' the King replied.
Here the other guinea-pig cheered, and was suppressed.
`Come, that finished the guinea-pigs!' thought Alice. `Now we
shall get on better.'
`I'd rather finish my tea,' said the Hatter, with an anxious
look at the Queen, who was reading the list of singers.
`You may go,' said the King, and the Hatter hurriedly left the
court, without even waiting to put his shoes on.
`--and just take his head off outside,' the Queen added to one
of the officers: but the Hatter was out of sight before the
officer could get to the door.
`Call the next witness!' said the King.
The next witness was the Duchess's cook. She carried the
pepper-box in her hand, and Alice guessed who it was, even before
she got into the court, by the way the people near the door began
sneezing all at once.
`Give your evidence,' said the King.
`Shan't,' said the cook.
The King looked anxiously at the White Rabbit, who said in a
low voice, `Your Majesty must cross-examine THIS witness.'
`Well, if I must, I must,' the King said, with a melancholy
air, and, after folding his arms and frowning at the cook till
his eyes were nearly out of sight, he said in a deep voice, `What
are tarts made of?'
`Pepper, mostly,' said the cook.
`Treacle,' said a sleepy voice behind her.
`Collar that Dormouse,' the Queen shrieked out. `Behead that
Dormouse! Turn that Dormouse out of court! Suppress him! Pinch
him! Off with his whiskers!'
For some minutes the whole court was in confusion, getting the
Dormouse turned out, and, by the time they had settled down
again, the cook had disappeared.
`Never mind!' said the King, with an air of great relief.
`Call the next witness.' And he added in an undertone to the
Queen, `Really, my dear, YOU must cross-examine the next witness.
It quite makes my forehead ache!'
Alice watched the White Rabbit as he fumbled over the list,
feeling very curious to see what the next witness would be like,
`--for they haven't got much evidence YET,' she said to herself.
Imagine her surprise, when the White Rabbit read out, at the top
of his shrill little voice, the name `Alice!'
CHAPTER XII
Alice's Evidence
`Here!' cried Alice, quite forgetting in the flurry of the
moment how large she had grown in the last few minutes, and she
jumped up in such a hurry that she tipped over the jury-box with
the edge of her skirt, upsetting all the jurymen on to the heads
of the crowd below, and there they lay sprawling about, reminding
her very much of a globe of goldfish she had accidentally upset
the week before.
`Oh, I BEG your pardon!' she exclaimed in a tone of great
dismay, and began picking them up again as quickly as she could,
for the accident of the goldfish kept running in her head, and
she had a vague sort of idea that they must be collected at once
and put back into the jury-box, or they would die.
`The trial cannot proceed,' said the King in a very grave
voice, `until all the jurymen are back in their proper places--
ALL,' he repeated with great emphasis, looking hard at Alice as
he said do.
Alice looked at the jury-box, and saw that, in her haste, she
had put the Lizard in head downwards, and the poor little thing
was waving its tail about in a melancholy way, being quite unable
to move. She soon got it out again, and put it right; `not that
it signifies much,' she said to herself; `I should think it
would be QUITE as much use in the trial one way up as the other.'
As soon as the jury had a little recovered from the shock of
being upset, and their slates and pencils had been found and
handed back to them, they set to work very diligently to write
out a history of the accident, all except the Lizard, who seemed
too much overcome to do anything but sit with its mouth open,
gazing up into the roof of the court.
`What do you know about this business?' the King said to
Alice.
`Nothing,' said Alice.
`Nothing WHATEVER?' persisted the King.
`Nothing whatever,' said Alice.
`That's very important,' the King said, turning to the jury.
They were just beginning to write this down on their slates, when
the White Rabbit interrupted: `UNimportant, your Majesty means,
of course,' he said in a very respectful tone, but frowning and
making faces at him as he spoke.
`UNimportant, of course, I meant,' the King hastily said, and
went on to himself in an undertone, `important--unimportant--
unimportant--important--' as if he were trying which word
sounded best.
Some of the jury wrote it down `important,' and some
`unimportant.' Alice could see this, as she was near enough to
look over their slates; `but it doesn't matter a bit,' she
thought to herself.
At this moment the King, who had been for some time busily
writing in his note-book, cackled out `Silence!' and read out
from his book, `Rule Forty-two. ALL PERSONS MORE THAN A MILE
HIGH TO LEAVE THE COURT.'
Everybody looked at Alice.
`I'M not a mile high,' said Alice.
`You are,' said the King.
`Nearly two miles high,' added the Queen.
`Well, I shan't go, at any rate,' said Alice: `besides,
that's not a regular rule: you invented it just now.'
`It's the oldest rule in the book,' said the King.
`Then it ought to be Number One,' said Alice.
The King turned pale, and shut his note-book hastily.
`Consider your verdict,' he said to the jury, in a low, trembling
voice.
`There's more evidence to come yet, please your Majesty,' said
the White Rabbit, jumping up in a great hurry; `this paper has
just been picked up.'
`What's in it?' said the Queen.
`I haven't opened it yet,' said the White Rabbit, `but it seems
to be a letter, written by the prisoner to--to somebody.'
`It must have been that,' said the King, `unless it was
written to nobody, which isn't usual, you know.'
`Who is it directed to?' said one of the jurymen.
`It isn't directed at all,' said the White Rabbit; `in fact,
there's nothing written on the OUTSIDE.' He unfolded the paper
as he spoke, and added `It isn't a letter, after all: it's a set
of verses.'
`Are they in the prisoner's handwriting?' asked another of
they jurymen.
`No, they're not,' said the White Rabbit, `and that's the
queerest thing about it.' (The jury all looked puzzled.)
`He must have imitated somebody else's hand,' said the King.
(The jury all brightened up again.)
`Please your Majesty,' said the Knave, `I didn't write it, and
they can't prove I did: there's no name signed at the end.'
`If you didn't sign it,' said the King, `that only makes the
matter worse. You MUST have meant some mischief, or else you'd
have signed your name like an honest man.'
There was a general clapping of hands at this: it was the
first really clever thing the King had said that day.
`That PROVES his guilt,' said the Queen.
`It proves nothing of the sort!' said Alice. `Why, you don't
even know what they're about!'
`Read them,' said the King.
The White Rabbit put on his spectacles. `Where shall I begin,
please your Majesty?' he asked.
`Begin at the beginning,' the King said gravely, `and go on
till you come to the end: then stop.'
These were the verses the White Rabbit read:--
`They told me you had been to her,
And mentioned me to him:
She gave me a good character,
But said I could not swim.
He sent them word I had not gone
(We know it to be true):
If she should push the matter on,
What would become of you?
I gave her one, they gave him two,
You gave us three or more;
They all returned from him to you,
Though they were mine before.
If I or she should chance to be
Involved in this affair,
He trusts to you to set them free,
Exactly as we were.
My notion was that you had been
(Before she had this fit)
An obstacle that came between
Him, and ourselves, and it.
Don't let him know she liked them best,
For this must ever be
A secret, kept from all the rest,
Between yourself and me.'
`That's the most important piece of evidence we've heard yet,'
said the King, rubbing his hands; `so now let the jury--'
`If any one of them can explain it,' said Alice, (she had
grown so large in the last few minutes that she wasn't a bit
afraid of interrupting him,) `I'll give him sixpence. _I_ don't
believe there's an atom of meaning in it.'
The jury all wrote down on their slates, `SHE doesn't believe
there's an atom of meaning in it,' but none of them attempted to
explain the paper.
`If there's no meaning in it,' said the King, `that saves a
world of trouble, you know, as we needn't try to find any. And
yet I don't know,' he went on, spreading out the verses on his
knee, and looking at them with one eye; `I seem to see some
meaning in them, after all. "--SAID I COULD NOT SWIM--" you
can't swim, can you?' he added, turning to the Knave.
The Knave shook his head sadly. `Do I look like it?' he said.
(Which he certainly did NOT, being made entirely of cardboard.)
`All right, so far,' said the King, and he went on muttering
over the verses to himself: `"WE KNOW IT TO BE TRUE--" that's
the jury, of course-- "I GAVE HER ONE, THEY GAVE HIM TWO--" why,
that must be what he did with the tarts, you know--'
`But, it goes on "THEY ALL RETURNED FROM HIM TO YOU,"' said
Alice.
`Why, there they are!' said the King triumphantly, pointing to
the tarts on the table. `Nothing can be clearer than THAT.
Then again--"BEFORE SHE HAD THIS FIT--" you never had fits, my
dear, I think?' he said to the Queen.
`Never!' said the Queen furiously, throwing an inkstand at the
Lizard as she spoke. (The unfortunate little Bill had left off
writing on his slate with one finger, as he found it made no
mark; but he now hastily began again, using the ink, that was
trickling down his face, as long as it lasted.)
`Then the words don't FIT you,' said the King, looking round
the court with a smile. There was a dead silence.
`It's a pun!' the King added in an offended tone, and
everybody laughed, `Let the jury consider their verdict,' the
King said, for about the twentieth time that day.
`No, no!' said the Queen. `Sentence first--verdict afterwards.'
`Stuff and nonsense!' said Alice loudly. `The idea of having
the sentence first!'
`Hold your tongue!' said the Queen, turning purple.
`I won't!' said Alice.
`Off with her head!' the Queen shouted at the top of her voice.
Nobody moved.
`Who cares for you?' said Alice, (she had grown to her full
size by this time.) `You're nothing but a pack of cards!'
At this the whole pack rose up into the air, and came flying
down upon her: she gave a little scream, half of fright and half
of anger, and tried to beat them off, and found herself lying on
the bank, with her head in the lap of her sister, who was gently
brushing away some dead leaves that had fluttered down from the
trees upon her face.
`Wake up, Alice dear!' said her sister; `Why, what a long
sleep you've had!'
`Oh, I've had such a curious dream!' said Alice, and she told
her sister, as well as she could remember them, all these strange
Adventures of hers that you have just been reading about; and
when she had finished, her sister kissed her, and said, `It WAS a
curious dream, dear, certainly: but now run in to your tea; it's
getting late.' So Alice got up and ran off, thinking while she
ran, as well she might, what a wonderful dream it had been.
But her sister sat still just as she left her, leaning her
head on her hand, watching the setting sun, and thinking of
little Alice and all her wonderful Adventures, till she too began
dreaming after a fashion, and this was her dream:--
First, she dreamed of little Alice herself, and once again the
tiny hands were clasped upon her knee, and the bright eager eyes
were looking up into hers--she could hear the very tones of her
voice, and see that queer little toss of her head to keep back
the wandering hair that WOULD always get into her eyes--and
still as she listened, or seemed to listen, the whole place
around her became alive the strange creatures of her little
sister's dream.
The long grass rustled at her feet as the White Rabbit hurried
by--the frightened Mouse splashed his way through the
neighbouring pool--she could hear the rattle of the teacups as
the March Hare and his friends shared their never-ending meal,
and the shrill voice of the Queen ordering off her unfortunate
guests to execution--once more the pig-baby was sneezing on the
Duchess's knee, while plates and dishes crashed around it--once
more the shriek of the Gryphon, the squeaking of the Lizard's
slate-pencil, and the choking of the suppressed guinea-pigs,
filled the air, mixed up with the distant sobs of the miserable
Mock Turtle.
So she sat on, with closed eyes, and half believed herself in
Wonderland, though she knew she had but to open them again, and
all would change to dull reality--the grass would be only
rustling in the wind, and the pool rippling to the waving of the
reeds--the rattling teacups would change to tinkling sheep-
bells, and the Queen's shrill cries to the voice of the shepherd
boy--and the sneeze of the baby, the shriek of the Gryphon, and
all thy other queer noises, would change (she knew) to the
confused clamour of the busy farm-yard--while the lowing of the
cattle in the distance would take the place of the Mock Turtle's
heavy sobs.
Lastly, she pictured to herself how this same little sister of
hers would, in the after-time, be herself a grown woman; and how
she would keep, through all her riper years, the simple and
loving heart of her childhood: and how she would gather about
her other little children, and make THEIR eyes bright and eager
with many a strange tale, perhaps even with the dream of
Wonderland of long ago: and how she would feel with all their
simple sorrows, and find a pleasure in all their simple joys,
remembering her own child-life, and the happy summer days.
THE END
================================================
FILE: interfaces/13-io/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io"
"os"
)
func main() {
// Stdin, Stdout, and Stderr are *os.File.
// #1: reads from the standard input
// ------------------------------------------------
// if err := read(os.Stdin); err != nil {
// fmt.Fprintln(os.Stderr, err)
// return
// }
// #2: writes to the standard output
// ------------------------------------------------
// buf := []byte("hi!\n")
// if err := write(os.Stdout, buf); err != nil {
// fmt.Fprintln(os.Stderr, err)
// return
// }
// #2b: reads the entire file content into memory.
// ------------------------------------------------
// buf, err := ioutil.ReadFile("alice.txt")
// if err != nil {
// fmt.Fprintln(os.Stderr, err)
// return
// }
// if err := write(os.Stdout, buf); err != nil {
// fmt.Fprintln(os.Stderr, err)
// return
// }
// #3: reads and writes with 32KB of memory
// no matter how large the source data is.
// ------------------------------------------------
if err := ioCopy(os.Stdout, os.Stdin); err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
}
// ioCopy streams from a file to another file.
// we use it to stream from the standard input to ouput.
func ioCopy(dst, src *os.File) error {
// Use a fixed-length buffer to efficiently read from src stream in chunks.
buf := make([]byte, 32768)
// read over and over again to read all the data.
for {
// read can read only up to the buffer length.
nr, er := src.Read(buf)
// only write data if there is something to write.
if nr > 0 {
_, ew := dst.Write(buf[:nr])
if ew != nil {
return ew
}
}
// io.EOF = there is nothing left to read—close the loop.
if er == io.EOF {
return nil
}
// Only return an error if the reading really fails.
if er != nil {
return er
}
}
return nil
}
// write example.
func write(dst *os.File, buf []byte) error {
nw, ew := dst.Write(buf)
fmt.Printf("wrote : %d bytes\n", nw)
fmt.Printf("write err: %v\n", ew)
return ew
}
// read example.
func read(src *os.File) error {
buf := make([]byte, 1024*32) // in the middle.
// buf := make([]byte, 148157) // defies the purpose of streaming.
// buf := make([]byte, 8) // too many chunking.
for {
nr, er := src.Read(buf)
// fmt.Printf("buf : %q\n", buf[0:nr])
fmt.Printf("read : %d bytes\n", nr)
fmt.Printf("read err : %v\n", er)
if er == io.EOF {
return nil
}
if er != nil {
return er
}
}
return nil
}
================================================
FILE: interfaces/14-io-reusable/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io"
"os"
)
func main() {
n, err := transfer()
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Printf("%d bytes transferred.\n", n)
}
func transfer() (n int64, err error) {
// stream from the standard input to the in-memory buffer in 32KB data chunks.
// os.Stdin.Read(...) -> os.Stdout.Write(...)
if n, err = io.Copy(os.Stdout, os.Stdin); err != nil {
return n, err
}
return n, err
}
// ioCopy streams from a file to another file.
// we use it to stream from the standard input to ouput.
func ioCopy(dst, src *os.File) error {
// Use a fixed-length buffer to efficiently read from src stream in chunks.
buf := make([]byte, 32768)
// read over and over again to read all the data.
for {
// read can read only up to the buffer length.
nr, er := src.Read(buf)
// only write data if there is something to write.
if nr > 0 {
_, ew := dst.Write(buf[:nr])
if ew != nil {
return ew
}
}
// io.EOF = there is nothing left to read—close the loop.
if er == io.EOF {
return nil
}
// Only return an error if the reading really fails.
if er != nil {
return er
}
}
return nil
}
================================================
FILE: interfaces/15-png-detector/.gitignore
================================================
rosie.unknown
================================================
FILE: interfaces/15-png-detector/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
)
func main() {
// initiate the transmission channel (http connection) to the webserver.
resp, err := http.Get("https://inancgumus.github.com/x/rosie.unknown")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
// close it so the http package can reuse the connection.
defer resp.Body.Close()
// resp.Body here is an io.ReadCloser: Read() + Close() methods.
// but in the transfer function it's an io.Reader: Only the Read() method.
n, err := transfer(resp.Body)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Printf("%d bytes transferred.\n", n)
// resp.Body.Close() runs here (because of the defer above)
}
func transfer(r io.Reader) (n int64, err error) {
const pngSign = "\x89PNG\r\n\x1a\n"
const pngSignLen = 8
// create an in-memory buffer (bytes.Buffer is an io.Reader and an io.Writer).
var memory bytes.Buffer
// stream from the standard input to the in-memory buffer in 32KB data chunks.
// r.Read(...) -> memory.Write(...)
if n, err = io.Copy(&memory, r); err != nil {
return n, err
}
// check the png signature.
buf := memory.Bytes()
fmt.Printf("% x\n", buf[:pngSignLen])
fmt.Printf("% x\n", pngSign)
return n, err
}
================================================
FILE: interfaces/16-io-compose/.gitignore
================================================
rosie.unknown
rosie.png
_other.go
toc
================================================
FILE: interfaces/16-io-compose/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"errors"
"fmt"
"io"
"net/http"
"os"
)
func main() {
resp, err := http.Get("https://inancgumus.github.com/x/rosie.unknown")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
defer resp.Body.Close()
// creates a file (or truncates if the file exists)
file, err := os.Create("rosie.png")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
defer file.Close()
n, err := transfer(resp.Body, file)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Printf("%d bytes transferred.\n", n)
// main() runs the deferred funcs in reverse order:
// file.Close()
// resp.Body.Close()
}
// transfer streams data from a reader to a writer.
// if the reader doesn't contain a PNG signature, transfer returns errNotPNG.
// otherwise, it transfers the data to the writer.
func transfer(r io.Reader, w io.Writer) (n int64, err error) {
const pngSign = "\x89PNG\r\n\x1a\n"
const pngSignLen = 8
var memory bytes.Buffer
// limit what copy() reads.
// lr := io.LimitReader(r, pngSignLen)
// if n, err = io.Copy(&memory, lr); err != nil {
// return n, err
// }
// same as above. behind the scenes CopyN() calls LimitReader.
if n, err = io.CopyN(&memory, r, pngSignLen); err != nil {
return n, err
}
// check the png signature.
if !bytes.HasPrefix(memory.Bytes(), []byte(pngSign)) {
return n, errors.New("not png")
}
// stitch the PNG signature (memory) and the response body reader together.
// then copy them successively to the writer (*os.File).
return io.Copy(w, io.MultiReader(&memory, r))
}
================================================
FILE: interfaces/17-write-an-io-reader/.gitignore
================================================
rosie.unknown
rosie.png
_other.go
toc
================================================
FILE: interfaces/17-write-an-io-reader/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
// resp, err := http.Get("https://inancgumus.github.com/x/rosie.jpg")
resp, err := http.Get("https://inancgumus.github.com/x/rosie.unknown")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
defer resp.Body.Close()
file, err := os.Create("rosie.png")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
defer file.Close()
n, err := io.Copy(file, pngReader(resp.Body))
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Printf("%d bytes transferred.\n", n)
}
================================================
FILE: interfaces/17-write-an-io-reader/reader.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"fmt"
"io"
)
// reader reads from `r` if the stream starts with a given signature.
// otherwise it stops and returns with an error.
type signatureReader struct {
r io.Reader // reads from the response.Body (or from any reader)
signature []byte // stream should start with this initial signature
}
// Read implements the io.Reader interface.
func (sr *signatureReader) Read(b []byte) (n int, err error) {
n, err = sr.r.Read(b)
l := len(sr.signature)
if l == 0 {
// simply return if the signature has already been detected.
return
}
// 1) buffer : **** -> b[:3] -> ***
// signature: *** -> sr.signature[:3] -> ***
// 2) buffer : ** -> b[:2] -> **
// signature: **** -> sr.signature[:2] -> **
if lb := len(b); lb < l {
l = lb
}
if got, want := b[:l], sr.signature[:l]; !bytes.Equal(got, want) {
err = fmt.Errorf("signature doesn't match, got: % x, want: % x", got, want)
}
// Assuming the `len(b)` is 4.
// 1st Read(): pr.signature[0:4] -> first part
// 2nd Read(): pr.signature[0:4] -> second part
sr.signature = sr.signature[l:]
return n, err
}
// create a reader for detecting only the png signatures.
func pngReader(r io.Reader) io.Reader {
return &signatureReader{
r: r,
signature: []byte("\x89PNG\r\n\x1a\n"),
}
}
================================================
FILE: interfaces/18-testing/.gitignore
================================================
rosie.unknown
rosie.png
_other.go
toc
================================================
FILE: interfaces/18-testing/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
// resp, err := http.Get("https://inancgumus.github.com/x/rosie.jpg")
resp, err := http.Get("https://inancgumus.github.com/x/rosie.unknown")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
defer resp.Body.Close()
file, err := os.Create("rosie.png")
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
defer file.Close()
n, err := io.Copy(file, pngReader(resp.Body))
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
fmt.Printf("%d bytes transferred.\n", n)
}
================================================
FILE: interfaces/18-testing/reader.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"fmt"
"io"
)
// reader reads from `r` if the stream starts with a given signature.
// otherwise it stops and returns with an error.
type signatureReader struct {
r io.Reader // reads from the response.Body (or from any reader)
signature []byte // stream should start with this initial signature
}
// Read implements the io.Reader interface.
func (sr *signatureReader) Read(b []byte) (n int, err error) {
n, err = sr.r.Read(b)
l := len(sr.signature)
if l == 0 {
return
}
if lb := len(b); lb < l {
l = lb
}
if got, want := b[:l], sr.signature[:l]; !bytes.Equal(got, want) {
err = fmt.Errorf("signature doesn't match, got: % x, want: % x", got, want)
}
sr.signature = sr.signature[l:]
return n, err
}
// create a reader for detecting only the png signatures.
func pngReader(r io.Reader) io.Reader {
return &signatureReader{
r: r,
signature: []byte("\x89PNG\r\n\x1a\n"),
}
}
================================================
FILE: interfaces/18-testing/reader_test.go
================================================
package main
import (
"io/ioutil"
"strings"
"testing"
)
func TestCorrectSignature(t *testing.T) {
const signature = "\x89PNG\r\n\x1a\n"
const input = signature + "REST OF THE DATA"
pr := pngReader(strings.NewReader(input))
out, err := ioutil.ReadAll(pr)
if err != nil {
t.Fatalf("got: %q; want: nil err", err)
}
if string(out) != input {
t.Fatalf("got: % x; want: % x", out, input)
}
}
func TestIncorrectSignature(t *testing.T) {
const input = "WITHOUT PNG SIGNATURE"
// strings.Reader is a read-only, in-memory stream reader.
// It's an io.Reader implementation.
pr := pngReader(strings.NewReader(input))
// `ioutil.ReadAll` is a dangerous but useful utility function
// that can read all the data from a reader into memory.
// Don't use it for large (?) data.
_, err := ioutil.ReadAll(pr)
if err == nil {
t.Fatalf("got: %v; want: !nil err", err)
}
}
func TestSummation(t *testing.T) {
t.Skip() // skip this test
result := 1 + 2
if result != 5 { // it'll always fail
// t.Fatal("want: 5") // not a good error message
t.Fatalf("got: %d; want: 5", result) // explanatory error message: good.
}
}
================================================
FILE: logparser/functional/Makefile
================================================
SHELL := /bin/bash
r:
go run . < ../logs/log.txt
t:
time go run . < ../logs/log.txt
================================================
FILE: logparser/functional/chartwriter.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// func chartWriter(w io.Writer) outputFn {
// return func(res []result) error {
// return chartWrite(w, res)
// }
// }
// func chartWrite(w io.Writer, res []result) error {
// sort.Slice(res, func(i, j int) bool {
// return res[i].domain > res[j].domain
// })
// donut := chart.DonutChart{
// Title: "Total Visits Per Domain",
// TitleStyle: chart.Style{
// FontSize: 35,
// Show: true,
// FontColor: chart.ColorAlternateGreen,
// },
// Width: 1920,
// Height: 800,
// }
// for _, r := range res {
// v := chart.Value{
// Label: r.domain + r.page + ": " + strconv.Itoa(r.visits),
// Value: float64(r.visits),
// Style: chart.Style{
// FontSize: 14,
// },
// }
// donut.Values = append(donut.Values, v)
// }
// return donut.Render(chart.SVG, w)
// }
================================================
FILE: logparser/functional/field.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"errors"
"fmt"
"strconv"
)
// field helps for field parsing
type field struct{ err error }
// uatoi parses an unsigned integer string and saves the error.
// it assumes that the val is unsigned.
// for ease of usability: it returns an int instead of uint.
func (f *field) uatoi(name, val string) int {
n, err := strconv.Atoi(val)
if err != nil || n < 0 {
f.err = fmt.Errorf("incorrect field -> %q = %q", name, val)
}
return n
}
func atoi(input []byte) (int, error) {
val := 0
for i := 0; i < len(input); i++ {
char := input[i]
if char < '0' || char > '9' {
return 0, errors.New("invalid number")
}
val = val*10 + int(char) - '0'
}
return val, nil
}
================================================
FILE: logparser/functional/filters.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "strings"
func noopFilter(r result) bool {
return true
}
func notUsing(filter filterFn) filterFn {
return func(r result) bool {
return !filter(r)
}
}
func domainExtFilter(domains ...string) filterFn {
return func(r result) bool {
for _, domain := range domains {
if strings.HasSuffix(r.domain, "."+domain) {
return true
}
}
return false
}
}
func domainFilter(domain string) filterFn {
return func(r result) bool {
return strings.Contains(r.domain, domain)
}
}
func orgDomainsFilter(r result) bool {
return strings.HasSuffix(r.domain, ".org")
}
================================================
FILE: logparser/functional/groupers.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// domainGrouper groups by domain.
// but it keeps the other fields.
// for example: it returns pages as well, but you shouldn't use them.
// exercise: write a function that erases superfluous data.
func domainGrouper(r result) string {
return r.domain
}
func pageGrouper(r result) string {
return r.domain + r.page
}
// groupBy allocates map unnecessarily
func noopGrouper(r result) string {
// with something like:
// return randomStrings()
return ""
}
================================================
FILE: logparser/functional/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
p := pipeline{
read: textReader(os.Stdin),
write: textWriter(os.Stdout),
filter: notUsing(domainExtFilter("io", "com")),
group: domainGrouper,
}
// var p pipeline
// p.
// filterBy(notUsing(domainExtFilter("io", "com"))).
// groupBy(domainGrouper)
if err := p.start(); err != nil {
fmt.Println("> Err:", err)
}
}
// []outputter{textFile("results.txt"), chartFile("graph.png")}
// func outputs(w io.Writer) outputFn {
// tw := textWriter(w)
// cw := chartWriter(w)
// return func(rs []result) error {
// err := tw(rs)
// err = cw(rs)
// return err
// }
// }
================================================
FILE: logparser/functional/pipeline.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "os"
type (
processFn func(r result)
inputFn func(processFn) error
outputFn func([]result) error
filterFn func(result) (include bool)
groupFn func(result) (key string)
)
type pipeline struct {
read inputFn
write outputFn
filter filterFn
group groupFn
}
func (p *pipeline) filterBy(f filterFn) *pipeline { p.filter = f; return p }
func (p *pipeline) groupBy(f groupFn) *pipeline { p.group = f; return p }
func (p *pipeline) from(f inputFn) *pipeline { p.read = f; return p }
func (p *pipeline) to(f outputFn) *pipeline { p.write = f; return p }
func (p *pipeline) defaults() {
if p.filter == nil {
p.filter = noopFilter
}
if p.group == nil {
p.group = domainGrouper
}
if p.read == nil {
p.read = textReader(os.Stdin)
}
if p.write == nil {
p.write = textWriter(os.Stdout)
}
}
func (p *pipeline) start() error {
p.defaults()
// retrieve and process the lines
sum := make(map[string]result)
process := func(r result) {
if !p.filter(r) {
return
}
k := p.group(r)
sum[k] = r.add(sum[k])
}
// return err from input reader
if err := p.read(process); err != nil {
return err
}
// prepare the results for outputting
var out []result
for _, res := range sum {
out = append(out, res)
}
// return err from output reader
return p.write(out)
}
================================================
FILE: logparser/functional/result.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strings"
)
const fieldsLength = 4
// result stores the parsed result for a domain
type result struct {
domain string
page string
visits int
uniques int
}
// add adds the metrics of another result
func (r result) add(other result) result {
r.visits += other.visits
r.uniques += other.uniques
return r
}
// parseFields parses and returns the parsing result
func parseFields(line string) (r result, err error) {
fields := strings.Fields(line)
if len(fields) != fieldsLength {
return r, fmt.Errorf("wrong number of fields %q", fields)
}
r.domain = fields[0]
r.page = fields[1]
f := new(field)
r.visits = f.uatoi("visits", fields[2])
r.uniques = f.uatoi("uniques", fields[3])
return r, f.err
}
func fastParseFields(data []byte) (res result, err error) {
const separator = ' '
var findex int
for i, j := 0, 0; i < len(data); i++ {
c := data[i]
last := len(data) == i+1
if c != separator && !last {
continue
}
if last {
i = len(data)
}
switch fval := data[j:i]; findex {
case 0:
res.domain = string(fval)
case 1:
res.page = string(fval)
case 2:
res.visits, err = atoi(fval)
case 3:
res.uniques, err = atoi(fval)
}
if err != nil {
return res, err
}
j = i + 1
findex++
}
if findex != fieldsLength {
err = fmt.Errorf("wrong number of fields %q", data)
}
return res, err
}
================================================
FILE: logparser/functional/textreader.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"io"
)
func textReader(r io.Reader) inputFn {
return func(process processFn) error {
var (
l = 1
in = bufio.NewScanner(r)
)
for in.Scan() {
r, err := fastParseFields(in.Bytes())
// r, err := parseFields(in.Text())
if err != nil {
return fmt.Errorf("line %d: %v", l, err)
}
process(r)
l++
}
if c, ok := r.(io.Closer); ok {
c.Close()
}
return in.Err()
}
}
================================================
FILE: logparser/functional/textwriter.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io"
"sort"
"strings"
)
// TODO: sort by result key interfaces section
const (
// DOMAINS PAGES VISITS UNIQUES
// ^ ^ ^ ^
// | | | |
header = "%-25s %-10s %10s %10s\n"
line = "%-25s %-10s %10d %10d\n"
footer = "\n%-36s %10d %10d\n" // -> "" VISITS UNIQUES
dash = "-"
dashLength = 58
)
func textWriter(w io.Writer) outputFn {
return func(res []result) error {
sort.Slice(res, func(i, j int) bool {
return res[i].domain > res[j].domain
})
var total result
fmt.Fprintf(w, header, "DOMAINS", "PAGES", "VISITS", "UNIQUES")
fmt.Fprintf(w, strings.Repeat(dash, dashLength)+"\n")
for _, r := range res {
total = total.add(r)
fmt.Fprintf(w, line, r.domain, r.page, r.visits, r.uniques)
}
fmt.Fprintf(w, footer, "", total.visits, total.uniques)
return nil
}
}
func noWhere() outputFn {
return func(res []result) error {
return nil
}
}
================================================
FILE: logparser/logs/Makefile
================================================
SHELL := /bin/bash
LINES = $$(wc -l log.txt | cut -f1 -d' ')
ECHO_LINES = echo -e ">> log.txt has $(LINES) lines"
n ?= 18
load: restore
@echo "enlarging the file with itself, please wait..."
@for i in {1..$(n)}; do \
awk 1 log.txt log.txt > log_.txt; \
mv log_.txt log.txt; \
rm -f log_.txt; \
done
@$(ECHO_LINES)
restore:
@echo "restoring the file..."
@git checkout log.txt
@$(ECHO_LINES)
multiply: remove
@echo "creating 20 log files..."
@for i in {1..20}; do \
echo log$${i}.txt; \
cp log.txt log$${i}.txt; \
done
remove:
rm -f log{1..20}.txt
lines:
@$(ECHO_LINES)
================================================
FILE: logparser/logs/log.jsonl
================================================
{"domain": "learngoprogramming.com", "page": "/", "visits": 10, "uniques": 5}
{"domain": "learngoprogramming.com", "page": "/courses", "visits": 15, "uniques": 10}
{"domain": "learngoprogramming.com", "page": "/courses", "visits": 10, "uniques": 5}
{"domain": "learngoprogramming.com", "page": "/articles", "visits": 20, "uniques": 15}
{"domain": "learngoprogramming.com", "page": "/articles", "visits": 5, "uniques": 2}
{"domain": "golang.org", "page": "/", "visits": 40, "uniques": 20}
{"domain": "golang.org", "page": "/", "visits": 20, "uniques": 10}
{"domain": "golang.org", "page": "/blog", "visits": 45, "uniques": 25}
{"domain": "golang.org", "page": "/blog", "visits": 15, "uniques": 5}
{"domain": "blog.golang.org", "page": "/courses", "visits": 60, "uniques": 30}
{"domain": "blog.golang.org", "page": "/courses", "visits": 30, "uniques": 20}
{"domain": "blog.golang.org", "page": "/updates", "visits": 20, "uniques": 10}
{"domain": "blog.golang.org", "page": "/reference", "visits": 65, "uniques": 35}
{"domain": "blog.golang.org", "page": "/reference", "visits": 15, "uniques": 5}
{"domain": "inanc.io", "page": "/about", "visits": 30, "uniques": 15}
{"domain": "inanc.io", "page": "/about","visits": 70, "uniques": 35}
================================================
FILE: logparser/logs/log.txt
================================================
learngoprogramming.com / 10 5
learngoprogramming.com /courses 15 10
learngoprogramming.com /courses 10 5
learngoprogramming.com /articles 20 15
learngoprogramming.com /articles 5 2
golang.org / 40 20
golang.org / 20 10
golang.org /blog 45 25
golang.org /blog 15 5
blog.golang.org /courses 60 30
blog.golang.org /courses 30 20
blog.golang.org /updates 20 10
blog.golang.org /reference 65 35
blog.golang.org /reference 15 5
inanc.io /about 30 15
inanc.io /about 70 35
================================================
FILE: logparser/logs/log_err_missing.jsonl
================================================
{"domain": "learngoprogramming.com", "page": "/", "visits": 10, "uniques": 5}
{"domain": "learngoprogramming.com", "visits": 15, "uniques": 10}
{"domain": "learngoprogramming.com", "page": "/courses", "visits": 10, "uniques": 5}
{"domain": "learngoprogramming.com", "page": "/articles", "visits": 20, "uniques": 15}
{"domain": "learngoprogramming.com", "page": "/articles", "visits": 5, "uniques": 2}
{"domain": "golang.org", "page": "/", "visits": 40, "uniques": 20}
{"domain": "golang.org", "page": "/", "visits": 20, "uniques": 10}
{"domain": "golang.org", "page": "/blog", "visits": 45, "uniques": 25}
{"domain": "golang.org", "page": "/blog", "visits": 15, "uniques": 5}
{"domain": "blog.golang.org", "page": "/courses", "visits": 60, "uniques": 30}
{"domain": "blog.golang.org", "page": "/courses", "visits": 30, "uniques": 20}
{"domain": "blog.golang.org", "page": "/updates", "visits": 20, "uniques": 10}
{"domain": "blog.golang.org", "page": "/reference", "visits": 65, "uniques": 35}
{"domain": "blog.golang.org", "page": "/reference", "visits": 15, "uniques": 5}
{"domain": "inanc.io", "page": "/about", "visits": 30, "uniques": 15}
{"domain": "inanc.io", "page": "/about","visits": 70, "uniques": 35}
================================================
FILE: logparser/logs/log_err_missing.txt
================================================
learngoprogramming.com / 10 5
learngoprogramming.com /courses 15 10
learngoprogramming.com /courses 10 5
learngoprogramming.com /articles 20 15
learngoprogramming.com /articles 5 2
golang.org / 40 20
golang.org / 20 10
golang.org /blog 45 25
golang.org /blog 15 5
blog.golang.org /updates
blog.golang.org /updates 30 20
blog.golang.org /updates 20 10
blog.golang.org /reference 65 35
blog.golang.org /reference 15 5
inanc.io /about 30 15
inanc.io /about 70 35
================================================
FILE: logparser/logs/log_err_negative.jsonl
================================================
{"domain": "learngoprogramming.com", "page": "/", "visits": 10, "uniques": 5}
{"domain": "learngoprogramming.com", "page": "/courses", "visits": 15, "uniques": 10}
{"domain": "learngoprogramming.com", "page": "/courses", "visits": 10, "uniques": 5}
{"domain": "learngoprogramming.com", "page": "/articles", "visits": 20, "uniques": -15}
{"domain": "learngoprogramming.com", "page": "/articles", "visits": 5, "uniques": 2}
{"domain": "golang.org", "page": "/", "visits": 40, "uniques": 20}
{"domain": "golang.org", "page": "/", "visits": 20, "uniques": 10}
{"domain": "golang.org", "page": "/blog", "visits": 45, "uniques": 25}
{"domain": "golang.org", "page": "/blog", "visits": 15, "uniques": 5}
{"domain": "blog.golang.org", "page": "/courses", "visits": 60, "uniques": 30}
{"domain": "blog.golang.org", "page": "/courses", "visits": 30, "uniques": 20}
{"domain": "blog.golang.org", "page": "/updates", "visits": 20, "uniques": 10}
{"domain": "blog.golang.org", "page": "/reference", "visits": 65, "uniques": 35}
{"domain": "blog.golang.org", "page": "/reference", "visits": 15, "uniques": 5}
{"domain": "inanc.io", "page": "/about", "visits": 30, "uniques": 15}
{"domain": "inanc.io", "page": "/about","visits": 70, "uniques": 35}
================================================
FILE: logparser/logs/log_err_negative.txt
================================================
learngoprogramming.com / 10 5
learngoprogramming.com /courses 15 10
learngoprogramming.com /courses 10 5
learngoprogramming.com /articles 20 15
learngoprogramming.com /articles 5 2
golang.org / 40 20
golang.org / 20 10
golang.org /blog 45 -250
golang.org /blog 15 5
blog.golang.org /updates 60 30
blog.golang.org /updates 30 20
blog.golang.org /updates 20 10
blog.golang.org /reference 65 35
blog.golang.org /reference 15 5
inanc.io /about 30 15
inanc.io /about 70 35
================================================
FILE: logparser/logs/log_err_str.jsonl
================================================
{"domain": "learngoprogramming.com", "page": "/", "visits": 10, "uniques": 5}
{"domain": "learngoprogramming.com", "page": "/courses", "visits": 15, "uniques": 10}
{"domain": "learngoprogramming.com", "page": "/courses", "visits": "TEN", "uniques": 5}
{"domain": "learngoprogramming.com", "page": "/articles", "visits": 20, "uniques": 15}
{"domain": "learngoprogramming.com", "page": "/articles", "visits": 5, "uniques": 2}
{"domain": "golang.org", "page": "/", "visits": 40, "uniques": 20}
{"domain": "golang.org", "page": "/", "visits": 20, "uniques": 10}
{"domain": "golang.org", "page": "/blog", "visits": 45, "uniques": 25}
{"domain": "golang.org", "page": "/blog", "visits": 15, "uniques": 5}
{"domain": "blog.golang.org", "page": "/courses", "visits": 60, "uniques": 30}
{"domain": "blog.golang.org", "page": "/courses", "visits": 30, "uniques": 20}
{"domain": "blog.golang.org", "page": "/updates", "visits": 20, "uniques": 10}
{"domain": "blog.golang.org", "page": "/reference", "visits": 65, "uniques": 35}
{"domain": "blog.golang.org", "page": "/reference", "visits": 15, "uniques": 5}
{"domain": "inanc.io", "page": "/about", "visits": 30, "uniques": 15}
{"domain": "inanc.io", "page": "/about","visits": 70, "uniques": 35}
================================================
FILE: logparser/logs/log_err_str.txt
================================================
learngoprogramming.com / 10 5
learngoprogramming.com /courses 15 10
learngoprogramming.com /courses 10 5
learngoprogramming.com /articles 20 15
learngoprogramming.com /articles 5 2
golang.org / 40 TWENTY
golang.org / 20 10
golang.org /blog 45 25
golang.org /blog 15 5
blog.golang.org /updates 60 30
blog.golang.org /updates 30 20
blog.golang.org /updates 20 10
blog.golang.org /reference 65 35
blog.golang.org /reference 15 5
inanc.io /about 30 15
inanc.io /about 70 35
================================================
FILE: logparser/testing/log.txt
================================================
learngoprogramming.com 10 200
learngoprogramming.com 10 300
golang.org 4 50
golang.org 6 100
blog.golang.org 20 25
blog.golang.org 10 1
================================================
FILE: logparser/testing/log_err_missing.txt
================================================
learngoprogramming.com 10 200
learngoprogramming.com 10
golang.org 4 50
golang.org 6 100
blog.golang.org 20 25
blog.golang.org 10 1
================================================
FILE: logparser/testing/log_err_negative.txt
================================================
learngoprogramming.com 10 200
learngoprogramming.com 10 300
golang.org -100 50
golang.org 6 100
blog.golang.org 20 25
blog.golang.org 10 1
================================================
FILE: logparser/testing/log_err_str.txt
================================================
learngoprogramming.com 10 200
learngoprogramming.com 10 THREE-HUNDRED
golang.org FOUR 50
golang.org 6 100
blog.golang.org 20 25
blog.golang.org 10 1
================================================
FILE: logparser/testing/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"os"
"github.com/inancgumus/learngo/logparser/testing/report"
)
func main() {
p := report.New()
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
p.Parse(in.Text())
}
summarize(p.Summarize(), p.Err(), in.Err())
}
================================================
FILE: logparser/testing/main_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// +build integration
// go test -tags=integration
package main_test
import (
"bytes"
"os/exec"
"strings"
"testing"
)
const (
okIn = `
a.com 1 2
b.com 3 4
a.com 4 5
b.com 6 7`
okOut = `
DOMAIN VISITS TIME SPENT
-----------------------------------------------------------------
a.com 5 7
b.com 9 11
TOTAL 14 18`
)
func TestSummary(t *testing.T) {
tests := []struct {
name, in, out string
}{
{"valid input", okIn, okOut},
{"missing fields", "a.com 1 2\nb.com 3", "> Err: line #2: missing fields: [b.com 3]"},
{"incorrect visits", "a.com 1 2\nb.com -1 1", `> Err: line #2: incorrect visits: "-1"`},
{"incorrect time spent", "a.com 1 2\nb.com 3 -1", `> Err: line #2: incorrect time spent: "-1"`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
run(t, strings.TrimSpace(tt.in), strings.TrimSpace(tt.out))
})
}
}
func run(t *testing.T, in, out string) {
cmd := exec.Command("go", "run", ".")
cmd.Stdin = strings.NewReader(in)
got, err := cmd.CombinedOutput()
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(got, []byte(out+"\n")) {
t.Fatalf("\nwant:\n%s\n\ngot:\n%s", out, got)
}
}
================================================
FILE: logparser/testing/report/parser.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package report
import (
"fmt"
)
// Parser parses the log file and generates a summary report.
type Parser struct {
summary *Summary // summarizes the parsing results
lines int // number of parsed lines (for the error messages)
lerr error // the last error occurred
}
// New returns a new parsing state.
func New() *Parser {
return &Parser{summary: newSummary()}
}
// Parse parses a log line and adds it to the summary.
func (p *Parser) Parse(line string) {
// if there was an error do not continue
if p.lerr != nil {
return
}
// chain the parser's error to the result's
res, err := parse(line)
if p.lines++; err != nil {
p.lerr = fmt.Errorf("line #%d: %s", p.lines, err)
return
}
p.summary.update(res)
}
// Summarize summarizes the parsing results.
// Only use it after the parsing is done.
func (p *Parser) Summarize() *Summary {
return p.summary
}
// Err returns the last error encountered
func (p *Parser) Err() error {
return p.lerr
}
================================================
FILE: logparser/testing/report/parser_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package report_test
import (
"strings"
"testing"
"github.com/inancgumus/learngo/logparser/testing/report"
)
func newParser(lines string) *report.Parser {
p := report.New()
p.Parse(lines)
return p
}
func TestParserLineErrs(t *testing.T) {
p := newParser("a.com 1 2")
p.Parse("b.com -1 -1")
want := "#2"
err := p.Err().Error()
if !strings.Contains(err, want) {
t.Errorf("want: %q; got: %q", want, err)
}
}
func TestParserStopsOnErr(t *testing.T) {
p := newParser("a.com 10 20")
p.Parse("b.com -1 -1")
p.Parse("neverparses.com 30 40")
s := p.Summarize()
if want, got := 10, s.Total().Visits; want != got {
t.Errorf("want: %d; got: %d", want, got)
}
}
func TestParserIncorrectFields(t *testing.T) {
tests := []struct {
in, name string
}{
{"a.com", "missing fields"},
{"a.com -1 2", "incorrect visits"},
{"a.com 1 -1", "incorrect time spent"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if p := newParser(tt.in); p.Err() == nil {
t.Errorf("in: %q; got: nil err", tt.in)
}
})
}
}
================================================
FILE: logparser/testing/report/result.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package report
import (
"fmt"
"strconv"
"strings"
)
// always put all the related things together as in here
// Result stores metrics for a domain
// it uses the value mechanics,
// because it doesn't have to update anything
type Result struct {
Domain string `json:"domain"`
Visits int `json:"visits"`
TimeSpent int `json:"time_spent"`
// add more metrics if needed
}
// add adds the metrics of another Result to itself and returns a new Result
func (r Result) add(other Result) Result {
return Result{
Domain: r.Domain,
Visits: r.Visits + other.Visits,
TimeSpent: r.TimeSpent + other.TimeSpent,
}
}
// parse parses a single log line
func parse(line string) (r Result, err error) {
fields := strings.Fields(line)
if len(fields) != 3 {
return r, fmt.Errorf("missing fields: %v", fields)
}
f := new(field)
r.Domain = fields[0]
r.Visits = f.atoi("visits", fields[1])
r.TimeSpent = f.atoi("time spent", fields[2])
return r, f.err
}
// field helps for field parsing
type field struct{ err error }
func (f *field) atoi(name, val string) int {
n, err := strconv.Atoi(val)
if n < 0 || err != nil {
f.err = fmt.Errorf("incorrect %s: %q", name, val)
}
return n
}
================================================
FILE: logparser/testing/report/summary.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package report
import (
"sort"
)
// Summary aggregates the parsing results
type Summary struct {
sum map[string]Result // metrics per domain
domains []string // unique domain names
total Result // total visits for all domains
}
// newSummary constructs and initializes a new summary
// You can't use its methods without pointer mechanics
func newSummary() *Summary {
return &Summary{sum: make(map[string]Result)}
}
// Update updates the report for the given parsing result
func (s *Summary) update(r Result) {
domain := r.Domain
if _, ok := s.sum[domain]; !ok {
s.domains = append(s.domains, domain)
}
// let the result handle the addition
// this allows us to manage the result in once place
// and this way it becomes easily extendable
s.total = s.total.add(r)
s.sum[domain] = r.add(s.sum[domain])
}
// Iterator returns `next()` to detect when the iteration ends,
// and a `cur()` to return the current result.
// iterator iterates sorted by domains.
func (s *Summary) Iterator() (next func() bool, cur func() Result) {
sort.Strings(s.domains)
// remember the last iterated result
var last int
next = func() bool {
defer func() { last++ }()
return len(s.domains) > last
}
cur = func() Result {
// returns a copy so the caller cannot change it
name := s.domains[last-1]
return s.sum[name]
}
return
}
// Total returns the total metrics
func (s *Summary) Total() Result {
return s.total
}
// For the interfaces section
//
// MarshalJSON marshals a report to JSON
// Alternative: unexported embedding
// func (s *Summary) MarshalJSON() ([]byte, error) {
// type total struct {
// *Result
// IgnoreDomain *string `json:"domain,omitempty"`
// }
// return json.Marshal(struct {
// Sum map[string]Result `json:"summary"`
// Domains []string `json:"domains"`
// Total total `json:"total"`
// }{
// Sum: s.sum, Domains: s.domains, Total: total{Result: &s.total},
// })
// }
================================================
FILE: logparser/testing/report/summary_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package report_test
import (
"testing"
"github.com/inancgumus/learngo/logparser/testing/report"
)
func TestSummaryTotal(t *testing.T) {
p := newParser("a.com 1 2")
p.Parse("b.com 3 4")
s := p.Summarize()
want := report.Result{Domain: "", Visits: 4, TimeSpent: 6}
if got := s.Total(); want != got {
t.Errorf("want: %+v; got: %+v", want, got)
}
}
func TestSummaryIterator(t *testing.T) {
p := newParser("a.com 1 2")
p.Parse("a.com 3 4")
p.Parse("b.com 5 6")
s := p.Summarize()
next, cur := s.Iterator()
wants := []report.Result{
{Domain: "a.com", Visits: 4, TimeSpent: 6},
{Domain: "b.com", Visits: 5, TimeSpent: 6},
}
for _, want := range wants {
t.Run(want.Domain, func(t *testing.T) {
if got := next(); !got {
t.Errorf("next(): want: %t; got: %t", true, got)
}
if got := cur(); want != got {
t.Errorf("cur(): want: %+v; got: %+v", want, got)
}
})
}
}
================================================
FILE: logparser/testing/summarize.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"encoding/json"
"fmt"
"os"
"strings"
"github.com/inancgumus/learngo/logparser/testing/report"
)
// summarize prints the parsing results.
//
// it prints the errors and returns if there are any.
//
// --json flag encodes to json and prints.
func summarize(sum *report.Summary, errors ...error) {
if errs(errors...) {
return
}
if args := os.Args[1:]; len(args) == 1 && args[0] == "--json" {
encode(sum)
return
}
stdout(sum)
}
// encodes the summary to json
func encode(sum *report.Summary) {
out, err := json.MarshalIndent(sum, "", "\t")
if err != nil {
panic(err)
}
os.Stdout.Write(out)
}
// prints the summary to standard out
func stdout(sum *report.Summary) {
const (
head = "%-30s %10s %20s\n"
val = "%-30s %10d %20d\n"
)
fmt.Printf(head, "DOMAIN", "VISITS", "TIME SPENT")
fmt.Println(strings.Repeat("-", 65))
for next, cur := sum.Iterator(); next(); {
r := cur()
fmt.Printf(val, r.Domain, r.Visits, r.TimeSpent)
}
t := sum.Total()
fmt.Printf("\n"+val, "TOTAL", t.Visits, t.TimeSpent)
}
// this variadic func simplifies the multiple error handling
func errs(errs ...error) (wasErr bool) {
for _, err := range errs {
if err != nil {
fmt.Printf("> Err: %s\n", err)
wasErr = true
}
}
return
}
================================================
FILE: logparser/v1/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v1/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v1/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v1/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v1/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
func main() {
var (
sum map[string]int // total visits per domain
domains []string // unique domain names
total int // total visits to all domains
lines int // number of parsed lines (for the error messages)
)
sum = make(map[string]int)
// Scan the standard-in line by line
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
lines++
// Parse the fields
fields := strings.Fields(in.Text())
if len(fields) != 2 {
fmt.Printf("wrong input: %v (line #%d)\n", fields, lines)
return
}
domain := fields[0]
// Sum the total visits per domain
visits, err := strconv.Atoi(fields[1])
if visits < 0 || err != nil {
fmt.Printf("wrong input: %q (line #%d)\n", fields[1], lines)
return
}
// Collect the unique domains
if _, ok := sum[domain]; !ok {
domains = append(domains, domain)
}
// Keep track of total and per domain visits
total += visits
sum[domain] += visits
}
// Print the visits per domain
sort.Strings(domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range domains {
visits := sum[domain]
fmt.Printf("%-30s %10d\n", domain, visits)
}
// Print the total visits for all domains
fmt.Printf("\n%-30s %10d\n", "TOTAL", total)
// Let's handle the error
if err := in.Err(); err != nil {
fmt.Println("> Err:", err)
}
}
================================================
FILE: logparser/v2/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v2/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v2/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v2/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
// result stores the parsed result for a domain
type result struct {
domain string
visits int
// add more metrics if needed
}
// parser keep tracks of the parsing
type parser struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total int // total visits for all domains
lines int // number of parsed lines (for the error messages)
}
func main() {
p := parser{sum: make(map[string]result)}
// Scan the standard-in line by line
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
p.lines++
// Parse the fields
fields := strings.Fields(in.Text())
if len(fields) != 2 {
fmt.Printf("wrong input: %v (line #%d)\n", fields, p.lines)
return
}
domain := fields[0]
// Sum the total visits per domain
visits, err := strconv.Atoi(fields[1])
if visits < 0 || err != nil {
fmt.Printf("wrong input: %q (line #%d)\n", fields[1], p.lines)
return
}
// Collect the unique domains
if _, ok := p.sum[domain]; !ok {
p.domains = append(p.domains, domain)
}
// Keep track of total and per domain visits
p.total += visits
// You cannot assign to composite values
// p.sum[domain].visits += visits
// create and assign a new copy of `visit`
p.sum[domain] = result{
domain: domain,
visits: visits + p.sum[domain].visits,
}
}
// Print the visits per domain
sort.Strings(p.domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range p.domains {
parsed := p.sum[domain]
fmt.Printf("%-30s %10d\n", domain, parsed.visits)
}
// Print the total visits for all domains
fmt.Printf("\n%-30s %10d\n", "TOTAL", p.total)
// Let's handle the error
if err := in.Err(); err != nil {
fmt.Println("> Err:", err)
}
}
================================================
FILE: logparser/v3/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v3/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v3/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v3/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v3/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
func main() {
p := newParser()
// Scan the standard-in line by line
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
p.lines++
parsed, err := parse(p, in.Text())
if err != nil {
fmt.Println(err)
return
}
p = update(p, parsed)
}
// Print the visits per domain
sort.Strings(p.domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range p.domains {
parsed := p.sum[domain]
fmt.Printf("%-30s %10d\n", domain, parsed.visits)
}
// Print the total visits for all domains
fmt.Printf("\n%-30s %10d\n", "TOTAL", p.total)
// Let's handle the error
if err := in.Err(); err != nil {
fmt.Println("> Err:", err)
}
}
================================================
FILE: logparser/v3/parser.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
// result stores the parsed result for a domain
type result struct {
domain string
visits int
// add more metrics if needed
}
// parser keep tracks of the parsing
type parser struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total int // total visits for all domains
lines int // number of parsed lines (for the error messages)
}
// newParser constructs, initializes and returns a new parser
func newParser() parser {
return parser{sum: make(map[string]result)}
}
// parse parses a log line and returns the parsed result with an error
func parse(p parser, line string) (parsed result, err error) {
fields := strings.Fields(line)
if len(fields) != 2 {
err = fmt.Errorf("wrong input: %v (line #%d)", fields, p.lines)
return
}
parsed.domain = fields[0]
parsed.visits, err = strconv.Atoi(fields[1])
if parsed.visits < 0 || err != nil {
err = fmt.Errorf("wrong input: %q (line #%d)", fields[1], p.lines)
return
}
return
}
// update updates the parser for the given parsing result
func update(p parser, parsed result) parser {
domain, visits := parsed.domain, parsed.visits
// Collect the unique domains
if _, ok := p.sum[domain]; !ok {
p.domains = append(p.domains, domain)
}
// Keep track of total and per domain visits
p.total += visits
// create and assign a new copy of `visit`
p.sum[domain] = result{
domain: domain,
visits: visits + p.sum[domain].visits,
}
return p
}
================================================
FILE: logparser/v4/log.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org 4
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v4/log_err_missing.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v4/log_err_negative.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org -100
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v4/log_err_str.txt
================================================
learngoprogramming.com 10
learngoprogramming.com 10
golang.org FOUR
golang.org 6
blog.golang.org 20
blog.golang.org 10
================================================
FILE: logparser/v4/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
func main() {
p := newParser()
in := bufio.NewScanner(os.Stdin)
for in.Scan() {
parsed := parse(p, in.Text())
update(p, parsed)
}
summarize(p)
dumpErrs([]error{in.Err(), err(p)})
}
// summarize summarizes and prints the parsing result
func summarize(p *parser) {
sort.Strings(p.domains)
fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS")
fmt.Println(strings.Repeat("-", 45))
for _, domain := range p.domains {
fmt.Printf("%-30s %10d\n", domain, p.sum[domain].visits)
}
fmt.Printf("\n%-30s %10d\n", "TOTAL", p.total)
}
// dumpErrs simplifies handling multiple errors
func dumpErrs(errs []error) {
for _, err := range errs {
if err != nil {
fmt.Println("> Err:", err)
}
}
}
================================================
FILE: logparser/v4/parser.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
"strings"
)
// result stores the parsed result for a domain
type result struct {
domain string
visits int
// add more metrics if needed
}
// parser keep tracks of the parsing
type parser struct {
sum map[string]result // metrics per domain
domains []string // unique domain names
total int // total visits for all domains
lines int // number of parsed lines (for the error messages)
lerr error // the last error occurred
}
// newParser constructs, initializes and returns a new parser
func newParser() *parser {
return &parser{sum: make(map[string]result)}
}
// parse parses a log line and returns the parsed result with an error
func parse(p *parser, line string) (r result) {
if p.lerr != nil {
return
}
p.lines++
fields := strings.Fields(line)
if len(fields) != 2 {
p.lerr = fmt.Errorf("wrong input: %v (line #%d)", fields, p.lines)
return
}
var err error
r.domain = fields[0]
r.visits, err = strconv.Atoi(fields[1])
if r.visits < 0 || err != nil {
p.lerr = fmt.Errorf("wrong input: %q (line #%d)", fields[1], p.lines)
}
return
}
// update updates all the parsing results using the given parsing result
func update(p *parser, r result) {
if p.lerr != nil {
return
}
// Collect the unique domains
if _, ok := p.sum[r.domain]; !ok {
p.domains = append(p.domains, r.domain)
}
// Keep track of total and per domain visits
p.total += r.visits
// create and assign a new copy of `visit`
p.sum[r.domain] = result{
domain: r.domain,
visits: r.visits + p.sum[r.domain].visits,
}
}
// err returns the last error encountered
func err(p *parser) error {
return p.lerr
}
================================================
FILE: logparser/v5/Makefile
================================================
r:
go run . < ../../logs/log.txt
t:
time go run . < ../../logs/log.txt
================================================
FILE: logparser/v5/filepipe.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"os"
"strings"
"github.com/inancgumus/learngo/logparser/v5/pipe"
)
// fromFile generates a default pipeline.
// Detects the correct parser by the file extension.
// Uses a TextReport and groups by domain.
func fromFile(path string) (*pipe.Pipeline, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
var src pipe.Iterator
switch {
case strings.HasSuffix(path, ".txt"):
src = pipe.NewTextLog(f)
case strings.HasSuffix(path, ".jsonl"):
src = pipe.NewJSONLog(f)
}
return pipe.New(
src,
pipe.NewTextReport(os.Stdout),
pipe.GroupBy(pipe.DomainGrouper),
), nil
}
================================================
FILE: logparser/v5/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"log"
"os"
)
func main() {
// p := pipe.Default(
// os.Stdin, os.Stdout,
// pipe.FilterBy(pipe.DomainExtFilter("com", "io")),
// pipe.GroupBy(pipe.DomainGrouper),
// )
p, err := fromFile(os.Args[1])
if err != nil {
log.Fatal(err)
}
if err := p.Run(); err != nil {
log.Fatal(err)
}
}
================================================
FILE: logparser/v5/passthrough.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"github.com/inancgumus/learngo/logparser/v5/pipe"
)
type passThrough struct {
pipe.Iterator
}
func (t *passThrough) Consume(results pipe.Iterator) error {
t.Iterator = results
return nil
}
func (t *passThrough) Each(yield func(pipe.Record) error) error {
pass := func(r pipe.Record) error {
// fmt.Println(r.Fields())
// fmt.Println(r.Int("visits"))
return yield(r)
}
return t.Iterator.Each(pass)
}
================================================
FILE: logparser/v5/pipe/chartreport.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
/*
// You need to run:
// go get -u github.com/wcharczuk/go-chart
// Chart renders a chart.
type Chart struct {
Title string
Width, Height int
w io.Writer
}
// NewChartReport returns a Chart report generator.
func NewChartReport(w io.Writer) *Chart {
return &Chart{w: w}
}
// Consume generates a chart report.
func (c *Chart) Consume(records Iterator) error {
w := os.Stdout
donut := chart.DonutChart{
Title: c.Title,
TitleStyle: chart.Style{
FontSize: 35,
Show: true,
FontColor: chart.ColorAlternateGreen,
},
Width: c.Width,
Height: c.Height,
}
err := records.Each(func(r Record) error {
v := chart.Value{
Label: r.Domain + r.Page + ": " + strconv.Itoa(r.Visits),
Value: float64(r.Visits),
Style: chart.Style{
FontSize: 14,
},
}
donut.Values = append(donut.Values, v)
return nil
})
if err != nil {
return err
}
return donut.Render(chart.SVG, w)
}
*/
================================================
FILE: logparser/v5/pipe/close.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import (
"io"
)
// readClose the reader if it's a io.Closer.
func readClose(r io.Reader) {
if rc, ok := r.(io.Closer); ok {
rc.Close()
}
}
================================================
FILE: logparser/v5/pipe/filter.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
// FilterFunc represents a filtering pipeline func.
// The type alias frees us from binding to a named type.
type FilterFunc = func(Record) (pass bool)
// Filter the records.
type Filter struct {
src Iterator
filters []FilterFunc
}
// FilterBy returns a new filter pipeline.
func FilterBy(fn ...FilterFunc) *Filter {
return &Filter{filters: fn}
}
// Consume the records for lazy filtering.
func (f *Filter) Consume(records Iterator) error {
f.src = records
return nil
}
// Each filtered records.
func (f *Filter) Each(yield func(Record) error) error {
records := func(r Record) error {
if !f.checkAll(r) {
return nil
}
return yield(r)
}
return f.src.Each(records)
}
// checkAll the filters against the record.
func (f *Filter) checkAll(r Record) bool {
for _, fi := range f.filters {
if !fi(r) {
return false
}
}
return true
}
================================================
FILE: logparser/v5/pipe/filters.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import "strings"
// NotFilter reverses a filter. True becomes false, and vice versa.
func NotFilter(filter FilterFunc) FilterFunc {
return func(r Record) bool {
return !filter(r)
}
}
// DomainExtFilter filters a set of domain extensions.
func DomainExtFilter(domains ...string) FilterFunc {
return func(r Record) bool {
for _, domain := range domains {
if strings.HasSuffix(r.domain, "."+domain) {
return true
}
}
return false
}
}
// DomainFilter filters a domain if it contains the given text.
func DomainFilter(text string) FilterFunc {
return func(r Record) bool {
return strings.Contains(r.domain, text)
}
}
// DomainOrgFilter filters only the ".org" domains.
func DomainOrgFilter(r Record) bool {
return strings.HasSuffix(r.domain, ".org")
}
================================================
FILE: logparser/v5/pipe/group.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import (
"sort"
)
// GroupFunc represents a grouping func that returns a grouping key.
// The type alias frees us from binding to a named type.
type GroupFunc = func(Record) (key string)
// Group records by a key.
type Group struct {
sum map[string]record // metrics per group key
keys []string // unique group keys
key GroupFunc
}
// GroupBy returns a new Group.
// It takes a group func that returns a group key.
// The returned group will group the record using the key.
func GroupBy(key GroupFunc) *Group {
return &Group{
sum: make(map[string]record),
key: key,
}
}
// Consume the records for grouping.
func (g *Group) Consume(records Iterator) error {
group := func(r Record) error {
k := g.key(r)
if _, ok := g.sum[k]; !ok {
g.keys = append(g.keys, k)
}
g.sum[k] = r.sum(g.sum[k])
return nil
}
return records.Each(group)
}
// Each sends the grouped and sorted records to upstream.
func (g *Group) Each(yield func(Record) error) error {
sort.Strings(g.keys)
for _, k := range g.keys {
err := yield(Record{g.sum[k]})
if err != nil {
return err
}
}
return nil
}
================================================
FILE: logparser/v5/pipe/groupers.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
// DomainGrouper groups the records by domain.
// It keeps the other fields intact.
// For example: It returns the page field as well.
// Exercise: Write a solution that removes the unnecessary data.
func DomainGrouper(r Record) string {
return r.domain
}
// Page groups records by page.
func Page(r Record) string {
return r.domain + r.page
}
================================================
FILE: logparser/v5/pipe/jsonlog.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import (
"encoding/json"
"io"
)
// JSON parses json records.
type JSON struct {
reader io.Reader
}
// NewJSONLog creates a json parser.
func NewJSONLog(r io.Reader) *JSON {
return &JSON{reader: r}
}
// Each sends the records from a reader to upstream.
func (j *JSON) Each(yield func(Record) error) error {
defer readClose(j.reader)
// Use the same record for unmarshaling.
var r Record
dec := json.NewDecoder(j.reader)
for {
err := dec.Decode(&r)
if err == io.EOF {
break
}
if err != nil {
return err
}
if err := yield(r); err != nil {
return err
}
}
return nil
}
================================================
FILE: logparser/v5/pipe/jsonreport.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import (
"encoding/json"
"io"
)
// JSONReport generates a JSON report.
type JSONReport struct {
w io.Writer
}
// NewJSONReport returns a JSON report generator.
func NewJSONReport(w io.Writer) *JSONReport {
return &JSONReport{w: w}
}
// Consume the records and generate a JSON report.
func (t *JSONReport) Consume(records Iterator) error {
enc := json.NewEncoder(t.w)
encode := func(r Record) error {
return enc.Encode(&r)
}
return records.Each(encode)
}
================================================
FILE: logparser/v5/pipe/logcount.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import "fmt"
// logCount counts the yielded records.
type logCount struct {
Iterator
n int
}
// Each yields to the inner iterator while counting the records.
// Reports the record number on an error.
func (lc *logCount) Each(yield func(Record) error) error {
count := func(r Record) error {
lc.n++
return yield(r)
}
err := lc.Iterator.Each(count)
if err != nil {
// lc.n+1: iterator.each won't call yield on err
return fmt.Errorf("record %d: %v", lc.n+1, err)
}
return nil
}
// count returns the last read record number.
func (lc *logCount) count() int {
return lc.n
}
================================================
FILE: logparser/v5/pipe/pipe.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
// Iterator yields a record.
type Iterator interface {
Each(func(Record) error) error
}
// Consumer consumes records from an iterator.
type Consumer interface {
Consume(Iterator) error
}
// Transform represents both a record consumer and producer.
// It has an input and output.
// It takes a single record and provides an iterator for all the records.
type Transform interface {
Iterator // producer: should never return on yield().err == nil
Consumer
}
================================================
FILE: logparser/v5/pipe/pipeline.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import (
"fmt"
"io"
"os"
)
// Pipeline takes records from a source, transforms, and sends them to a destionation.
type Pipeline struct {
src Iterator
trans []Transform
dst Consumer
}
// New creates a new pipeline.
func New(src Iterator, dst Consumer, t ...Transform) *Pipeline {
return &Pipeline{
src: &logCount{Iterator: src},
dst: dst,
trans: t,
}
}
// Default creates a pipeline that reads from a text log and generates a text report.
func Default(r io.Reader, w io.Writer, t ...Transform) *Pipeline {
return New(NewTextLog(r), NewTextReport(w), t...)
}
// Run the pipeline.
func (p *Pipeline) Run() error {
defer func() {
n := p.src.(*logCount).count()
fmt.Fprintf(os.Stderr, "%d records processed.\n", n)
}()
last := p.src
for _, t := range p.trans {
if err := t.Consume(last); err != nil {
return err
}
last = t
}
return p.dst.Consume(last)
}
================================================
FILE: logparser/v5/pipe/record.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import (
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
)
const fieldsLength = 4
// record stores fields of a log line.
type record struct {
domain string
page string
visits int
uniques int
}
// recordJSON is used for marshaling and unmarshaling JSON.
type recordJSON struct {
Domain string
Page string
Visits int
Uniques int
}
// sum the numeric fields with another record.
func (r record) sum(other record) record {
r.visits += other.visits
r.uniques += other.uniques
return r
}
// UnmarshalText to a *record.
func (r *record) UnmarshalText(p []byte) (err error) {
fields := strings.Fields(string(p))
if len(fields) != fieldsLength {
return fmt.Errorf("wrong number of fields %q", fields)
}
r.domain, r.page = fields[0], fields[1]
if r.visits, err = parseStr("visits", fields[2]); err != nil {
return err
}
if r.uniques, err = parseStr("uniques", fields[3]); err != nil {
return err
}
return validate(*r)
}
// UnmarshalJSON to a *record.
func (r *record) UnmarshalJSON(data []byte) error {
var rj recordJSON
if err := json.Unmarshal(data, &rj); err != nil {
return err
}
*r = record{rj.Domain, rj.Page, rj.Visits, rj.Uniques}
return validate(*r)
}
// MarshalJSON of a *record.
func (r *record) MarshalJSON() ([]byte, error) {
rj := recordJSON{r.domain, r.page, r.visits, r.uniques}
return json.Marshal(rj)
}
// parseStr helps UnmarshalText for string to positive int parsing.
func parseStr(name, v string) (int, error) {
n, err := strconv.Atoi(v)
if err != nil {
return 0, fmt.Errorf("Record.UnmarshalText %q: %v", name, err)
}
return n, nil
}
// validate whether a parsed record is valid or not.
func validate(r record) (err error) {
switch {
case r.domain == "":
err = errors.New("record.domain cannot be empty")
case r.page == "":
err = errors.New("record.page cannot be empty")
case r.visits < 0:
err = errors.New("record.visits cannot be negative")
case r.uniques < 0:
err = errors.New("record.uniques cannot be negative")
}
return
}
================================================
FILE: logparser/v5/pipe/recordshare.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import (
"fmt"
"reflect"
)
// Record stores the log line fields.
// The underlying fields are kept hidden.
// The users of the package are decoupled from the underlying record fields.
// When the fields change, the client won't feel the difference (at least in compile-time).
type Record struct {
record
}
// Str returns a string field. Panics when the field doesn't exist.
func (r Record) Str(field string) string {
return r.mustGet(field, reflect.String).String()
}
// Int returns an int field. Panics when the field doesn't exist.
func (r Record) Int(field string) int {
return int(r.mustGet(field, reflect.Int).Int())
}
// Fields returns all the field names.
// The names can be used to query the Record.
func (r Record) Fields() (fields []string) {
t := reflect.TypeOf(record{})
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
s := fmt.Sprintf("(%s: %s)", f.Name, f.Type.Name())
fields = append(fields, s)
}
return
}
// mustGet the field with the same kind or panics.
func (r Record) mustGet(field string, kind reflect.Kind) reflect.Value {
v := reflect.ValueOf(r.record).FieldByName(field)
if !v.IsValid() {
panic(fmt.Errorf("record.%s does not exist", field))
}
if v.Kind() != kind {
panic(fmt.Errorf("record.%s is not %q", field, kind))
}
return v
}
================================================
FILE: logparser/v5/pipe/textlog.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import (
"bufio"
"io"
)
// TextLog parses text based log lines.
type TextLog struct {
reader io.Reader
}
// NewTextLog creates a text parser.
func NewTextLog(r io.Reader) *TextLog {
return &TextLog{reader: r}
}
// Each yields records from a text log.
func (p *TextLog) Each(yield func(Record) error) error {
defer readClose(p.reader)
// Use the same record for unmarshaling.
var r Record
in := bufio.NewScanner(p.reader)
for in.Scan() {
if err := r.UnmarshalText(in.Bytes()); err != nil {
return err
}
if err := yield(r); err != nil {
return err
}
}
return in.Err()
}
================================================
FILE: logparser/v5/pipe/textreport.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package pipe
import (
"fmt"
"io"
"text/tabwriter"
)
const (
minWidth = 0
tabWidth = 4
padding = 4
flags = 0
)
// TextReport report generator.
type TextReport struct {
w io.Writer
}
// NewTextReport returns a TextReport report generator.
func NewTextReport(w io.Writer) *TextReport {
return &TextReport{w: w}
}
// Consume generates a text report.
func (t *TextReport) Consume(records Iterator) error {
w := tabwriter.NewWriter(t.w, minWidth, tabWidth, padding, ' ', flags)
fmt.Fprintf(w, "DOMAINS\tPAGES\tVISITS\tUNIQUES\n")
fmt.Fprintf(w, "-------\t-----\t------\t-------\n")
var total record
printLine := func(r Record) error {
total = r.sum(total)
fmt.Fprintf(w, "%s\t%s\t%d\t%d\n",
r.domain, r.page,
r.visits, r.uniques,
)
return nil
}
if err := records.Each(printLine); err != nil {
return err
}
fmt.Fprintf(w, "\t\t\t\n")
fmt.Fprintf(w, "%s\t%s\t%d\t%d\n", "TOTAL", "",
total.visits,
total.uniques,
)
return w.Flush()
}
================================================
FILE: logparser/v6/logly/parse/count.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package parse
import "fmt"
// Count the parsed records.
type Count struct {
// Parser is wrapped by Count to count the parsed records.
Parser
count int
}
// CountRecords creates a record counter that wraps a parser.
func CountRecords(p Parser) *Count {
return &Count{Parser: p}
}
// Parse increments the counter.
func (c *Count) Parse() bool {
c.count++
return c.Parser.Parse()
}
// Err returns the first error that was encountered by the Log.
func (c *Count) Err() (err error) {
err = c.Parser.Err()
if err != nil {
err = fmt.Errorf("record #%d: %v", c.count, err)
}
return
}
// You don't need to implement the Value() method.
// Thanks to interface embedding.
================================================
FILE: logparser/v6/logly/parse/json.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package parse
import (
"encoding/json"
"io"
"github.com/inancgumus/learngo/logparser/v6/logly/record"
)
// JSONParser parses json records.
type JSONParser struct {
in *json.Decoder
err error // last error
last *record.Record // last parsed record
}
// JSON creates a json parser.
func JSON(r io.Reader) *JSONParser {
return &JSONParser{
in: json.NewDecoder(r),
last: new(record.Record),
}
}
// Parse the next line.
func (p *JSONParser) Parse() bool {
if p.err != nil {
return false
}
p.last.Reset()
err := p.in.Decode(&p.last)
if err == io.EOF {
return false
}
p.err = err
return err == nil
}
// Value returns the most recent record parsed by a call to Parse.
func (p *JSONParser) Value() record.Record {
return *p.last
}
// Err returns the first error that was encountered by the Log.
func (p *JSONParser) Err() error {
return p.err
}
================================================
FILE: logparser/v6/logly/parse/parser.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package parse
import "github.com/inancgumus/learngo/logparser/v6/logly/record"
// Parser is an interface for the parsers.
type Parser interface {
// Parse the next record from the source.
Parse() bool
// Value returns the last parsed record by a call to Parse.
Value() record.Record
// Err returns the first error that was encountered.
Err() error
}
================================================
FILE: logparser/v6/logly/parse/text.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package parse
import (
"bufio"
"io"
"github.com/inancgumus/learngo/logparser/v6/logly/record"
)
// TextParser parses text based log lines.
type TextParser struct {
in *bufio.Scanner
err error // last error
last *record.Record // last parsed record
}
// Text creates a text parser.
func Text(r io.Reader) *TextParser {
return &TextParser{
in: bufio.NewScanner(r),
last: new(record.Record),
}
}
// Parse the next line.
func (p *TextParser) Parse() bool {
if p.err != nil {
return false
}
if !p.in.Scan() {
return false
}
p.err = p.last.FromText(p.in.Bytes())
return true
}
// Value returns the most recent record parsed by a call to Parse.
func (p *TextParser) Value() record.Record {
return *p.last
}
// Err returns the first error that was encountered by the Log.
func (p *TextParser) Err() error {
return p.err
}
================================================
FILE: logparser/v6/logly/record/json.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package record
import "encoding/json"
// UnmarshalJSON to a record.
func (r *Record) UnmarshalJSON(data []byte) error {
type rjson Record
err := json.Unmarshal(data, (*rjson)(r))
if err != nil {
return err
}
return r.validate()
}
================================================
FILE: logparser/v6/logly/record/record.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package record
const fieldsLength = 4
// Record stores fields of a log line.
type Record struct {
Domain string
Page string
Visits int
Uniques int
}
// Sum the numeric fields with another record.
func (r *Record) Sum(other Record) {
r.Visits += other.Visits
r.Uniques += other.Uniques
}
// Reset all the fields of this record.
func (r *Record) Reset() {
r.Domain = ""
r.Page = ""
r.Visits = 0
r.Uniques = 0
}
================================================
FILE: logparser/v6/logly/record/sum.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package record
// Sum groups the records by summing their numeric fields.
type Sum struct {
sum map[string]Record
}
// SumGroup the records by domain.
func SumGroup() *Sum {
return &Sum{
sum: make(map[string]Record),
}
}
// Group the record.
func (s *Sum) Group(r Record) {
k := r.Domain
r.Sum(s.sum[k])
s.sum[k] = r
}
// Records returns the grouped records.
func (s *Sum) Records() []Record {
var out []Record
for _, res := range s.sum {
out = append(out, res)
}
return out
}
================================================
FILE: logparser/v6/logly/record/text.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package record
import (
"fmt"
"strconv"
"strings"
)
// FromText unmarshals the log line into this record.
func (r *Record) FromText(p []byte) (err error) {
fields := strings.Fields(string(p))
if len(fields) != fieldsLength {
return fmt.Errorf("wrong number of fields %q", fields)
}
r.Domain = fields[0]
r.Page = fields[1]
const msg = "record.UnmarshalText %q: %v"
if r.Visits, err = strconv.Atoi(fields[2]); err != nil {
return fmt.Errorf(msg, "visits", err)
}
if r.Uniques, err = strconv.Atoi(fields[3]); err != nil {
return fmt.Errorf(msg, "uniques", err)
}
return r.validate()
}
================================================
FILE: logparser/v6/logly/record/validate.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package record
import "errors"
// validate whether the current record is valid or not.
func (r *Record) validate() error {
var msg string
switch {
case r.Domain == "":
msg = "record.domain cannot be empty"
case r.Page == "":
msg = "record.page cannot be empty"
case r.Visits < 0:
msg = "record.visits cannot be negative"
case r.Uniques < 0:
msg = "record.uniques cannot be negative"
}
if msg != "" {
return errors.New(msg)
}
return nil
}
================================================
FILE: logparser/v6/logly/report/json.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package report
import (
"encoding/json"
"io"
"github.com/inancgumus/learngo/logparser/v6/logly/record"
)
// JSON generates a json report.
func JSON(w io.Writer, rs []record.Record) error {
enc := json.NewEncoder(w)
for _, r := range rs {
err := enc.Encode(&r)
if err != nil {
return err
}
}
return nil
}
================================================
FILE: logparser/v6/logly/report/text.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package report
import (
"fmt"
"io"
"text/tabwriter"
"github.com/inancgumus/learngo/logparser/v6/logly/record"
)
// Text generates a text report.
func Text(w io.Writer, rs []record.Record) error {
tw := tabwriter.NewWriter(
w,
0, // minWidth
4, // tabWidth
4, // padding
' ', // padChar
0, // flags
)
fmt.Fprintf(tw, "DOMAINS\tPAGES\tVISITS\tUNIQUES\n")
fmt.Fprintf(tw, "-------\t-----\t------\t-------\n")
var total record.Record
for _, r := range rs {
total.Sum(r)
fmt.Fprintf(tw, "%s\t%s\t%d\t%d\n",
r.Domain, r.Page,
r.Visits, r.Uniques,
)
}
fmt.Fprintf(tw, "\t\t\t\n")
fmt.Fprintf(tw, "%s\t%s\t%d\t%d\n",
"TOTAL", "",
total.Visits, total.Uniques,
)
return tw.Flush()
}
================================================
FILE: logparser/v6/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"log"
"os"
"github.com/inancgumus/learngo/logparser/v6/logly/parse"
"github.com/inancgumus/learngo/logparser/v6/logly/record"
"github.com/inancgumus/learngo/logparser/v6/logly/report"
)
func main() {
var (
p = parse.CountRecords(parse.Text(os.Stdin))
g = record.SumGroup()
)
for p.Parse() {
g.Group(p.Value())
}
if err := p.Err(); err != nil {
log.Fatal(err)
}
if err := report.Text(os.Stdout, g.Records()); err != nil {
log.Fatal(err)
}
}
================================================
FILE: magic/detect.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package magic
import (
"bytes"
"errors"
"fmt"
"io"
"os"
)
// Detect returns the files that have a valid header (file signature).
// A valid header is determined by the format.
func Detect(format string, filenames []string) (valids []string, err error) {
header := headerOf(format)
if header == "unknown" {
err = fmt.Errorf("unknown format: %s", format)
return
}
buf := make([]byte, len(header))
for _, filename := range filenames {
if read(filename, buf) != nil {
continue
}
if bytes.Equal([]byte(header), buf) {
valids = append(valids, filename)
}
}
return
}
func headerOf(format string) string {
switch format {
case "png":
return "\x89PNG\r\n\x1a\n"
case "jpg":
return "\xff\xd8\xff"
}
// this should never occur
// panic("unknown format: " + format)
return "unknown"
}
// read reads len(buf) bytes to buf from a file
func read(filename string, buf []byte) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
fi, err := file.Stat()
if err != nil {
return err
}
if fi.Size() <= int64(len(buf)) {
return errors.New("file size < len(buf)")
}
_, err = io.ReadFull(file, buf)
return err
}
================================================
FILE: magicpanic/detect.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package magic
import (
"bytes"
"fmt"
"io"
"os"
)
// Detect returns the files that have a valid header (file signature).
// A valid header is determined by the format.
func Detect(format string, filenames []string) (valids []string, err error) {
defer func() {
if rerr := recover(); rerr != nil {
err = fmt.Errorf("cannot detect: %v", rerr)
}
}()
return detect(format, filenames), nil
}
func detect(format string, filenames []string) (valids []string) {
header := headerOf(format)
buf := make([]byte, len(header))
for _, filename := range filenames {
if read(filename, buf) != nil {
continue
}
if bytes.Equal([]byte(header), buf) {
valids = append(valids, filename)
}
}
return
}
func headerOf(format string) string {
switch format {
case "png":
return "\x89PNG\r\n\x1a\n"
case "jpg":
return "\xff\xd8\xff"
}
// this should never occur
panic("unknown format: " + format)
}
// read reads len(buf) bytes to buf from a file
func read(filename string, buf []byte) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
fi, err := file.Stat()
if err != nil {
return err
}
if fi.Size() <= int64(len(buf)) {
return fmt.Errorf("file size < len(buf)")
}
_, err = io.ReadFull(file, buf)
return err
}
================================================
FILE: main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hi Gopher!")
}
================================================
FILE: translation/README.md
================================================
# This Repo Is Available In The Following Languages
* **[English](https://github.com/inancgumus/learngo)**
* **[Spanish](spanish/README.md)**
================================================
FILE: translation/chinese/01-安装与介绍/README.md
================================================
# GO 安装指引
请根据你的操作系统获取安装详情
* [OS X](osx-安装指南.md)
* [Windows](windows-安装指南.md)
* [Linux (Ubuntu)](ubuntu-安装指南.md)
================================================
FILE: translation/chinese/01-安装与介绍/osx-安装指南.md
================================================
# OS X 安装
## 提示
如果已经安装好[homebrew](https://brew.sh), 可以按照如下步骤安装Go
```
# 安装git可以参照如下命令:
brew install git
# go 安装命令
brew install go
# 添加 GOBIN 路径 ~/.bash_profile
export PATH=${HOME}/go/bin:$PATH
```
## 1- 安装 Visual Studio Code Editor
1. 安装地址: [https://code.visualstudio.com](https://code.visualstudio.com)
2. 选择 OS X (Mac) 下载
3. 解压 添加到应用程序`~/Applications`路径.
## 2- 安装 Git
1. 下载Git. 官网: [https://git-scm.com/downloads](https://git-scm.com/downloads)
2. 选择VSCode为默认编辑器
## 3- 安装 Go
1. 官网 [https://golang.org/dl](https://golang.org/dl)
2. 选择 OS X (Mac)
3. 下载
## 4- 配置 VS Code
1. 打开 VS Code; 点击扩展插件功能, 搜索 "go" 下载
2. 下载完成后重启VS Code
3. 选择 View 菜单; 选择 **Command Palette**
1. 输入 `cmd+shift+p`
2. 输入: `go install`
3. 选择 _"Go: Install/Update Tools"_
4. 选择所有 checkboxes
4. 重启 **Command Palette**
1. 输入: `shell`
2. 选择: _"Install 'code' command in PATH"_
1. **提示:** Windows操作系统不需要上述操作.
## 工作完成! Enjoy! 🤩
> 更多内容: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2018 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/chinese/01-安装与介绍/ubuntu-安装指南.md
================================================
# Linux 安装指南
如果,只需要安装Go,请执行如下指令:
sudo snap install go --classic
否则, 请按如下安装步骤安装:
## 1. 更新本地依赖包
```bash
sudo apt-get update
```
## 2. 安装 git
```bash
sudo apt-get install git
```
## 3. 安装 Go
安装Go环境有如下两种方法:
1- 网站: 选择 Linux 版本并安装.
```bash
firefox https://golang.org/dl
```
2- 使用snap: 如果选择snap安装, 可以直接跳到步骤5.
```bash
sudo snap install go --classic
```
## 4. 将Go拷贝到适当的工作目录
1. 找到下载好的文件
2. 解压文件
```bash
gofile="DELETE_THIS_AND_TYPE_THE_NAME_OF_THE_DOWNLOADED_FILE_HERE (替换为下载文件,省去后缀)"
tar -C /usr/local -xzf ~/Downloads/$gofile
```
## 5. 添加Go的可执行路径
1. 添加`go/bin`目录到 `$PATH`, 以便执行Go的基础命令.
```bash
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
```
2. 添加 "$HOME/go/bin" 目录到 $PATH
```bash
echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.profile
```
## 安装Go工具:
* 有很多开发工具,可以让简化Go的开发 (如 goimports)
* 如果系统中没有安装代码版本工具(如 Git), 将无法使用`go get`.
* 上述命令会创建`~/go` 目录并下载到相应目录中.
* 此目录也将是我们存放代码的目录.(如果不实用Go Modules)
```bash
go get -v -u golang.org/x/tools/...
```
## 安装 VSCode (可选)
提示: 本课程将使用Visual Studio Code (VSCode). 但是, 可以使用任何代码编辑工具.
1. 打开 "Ubuntu Software" 应用
2. 搜索并安装VSCode
## 可选步骤:
1. 在`$GOPATH`之外的任何路径创建文件 hello.go
```bash
cat < hello.go
package main
import "fmt"
func main() {
fmt.Println("hello gopher!")
}
EOF
```
2. 执行程序
```bash
go run hello.go
It should print: hello gopher!
```
> 更多内容: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2018 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/chinese/01-安装与介绍/windows-安装指南.md
================================================
# WINDOWS 安装指南
## 笔记
如果已安装 [chocolatey.org](https://chocolatey.org/) 包管理工具, 可以通过如下命令安装:
```
choco install golang
```
## 1- 安装 Visual Studio Code Editor
1. 安装但是不要直接打开.
2. 打开 : [https://code.visualstudio.com](https://code.visualstudio.com)
3. 选择 Windows并进行安装
4. 执行installer
## 2- 安装 Git
1. 通过官网下载和安装. 官网地址: [https://gitforwindows.org](https://gitforwindows.org)
2. 选择 VSCode为默认编辑器
3. 勾选所以复选框,启用所有可选功能
4. 选择: _"Use Git from the Windows Command Prompt"_
5. 编码: 选择: _"Checkout as is..." option._
## 3- 安装 Go
1. 登陆Go官网 [https://golang.org/dl](https://golang.org/dl)
2. 选择 Windows版本下载
3. 执行Go安装器
## 4- 配置 VS Code
1. 运行 VS Code;在插件市场搜索"go"并安装
2. 关闭 VS Code并重新打开
3. 前往视图菜单; 选择 **Command Palette**
1. 执行 `ctrl+shift+p`
2. 键入: `go install`
3. 选择 _"Go: Install/Update Tools"_
4. 勾选所有复选框
## 5- 使用 Git-Bash
* 在本课程我们将使用bash作为命令行. Bash是在OS X 和 Linux系统上非常流行的命令行工具.
如果你也希望使用bash 而不是Windows提供的默认命令行, 可以使用已安装的bash命令行, 好似使用OS X 和 Linux系统.
* 如果您不打算使用git bash也是可以的. 但是, 本课程将使用git bash. git bash可以提供本课程需要的许多高级特性.
* 您也可以选择更加强大的工具来替代 git bash, 参考: [Linux Subsystem for Windows](https://docs.microsoft.com/en-us/windows/wsl/install-win10)
* **因此, 如果使用 git bash, 请遵守如下步骤:**
1. 在开始栏搜索git bash
2. 或者, 如果已经下载可以直接启用
3. 设置 VS Code 默认使用 git-bash:
1. 启动 VS Code
2. 转到命令面板
1. 输入: `terminal`
2. 选择: _"Terminal: Select Default Shell"_
3. 选择: _"Git Bash"_
4. **提示:** 一般, 可以在 `c:\`文件夹找到自定义文件. 但是, 档我们使用git bash, 自定义问价会在文件夹 `/c/`. 事实上,这两个文件目录是同一个目录, 只是一个软链接.
## 以上步骤完成,就可以使用了! 🤩
> 更多资料, 参考: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2018 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/chinese/01-安装与介绍/学习路线.md
================================================
# 学习路线
大家好!
如果您是有经验的开发者, 您只需要跟着课程学习50个小节即可,完整的课程是180节。
本课程从Go基础内容开始,逐渐递进。我们希望让尽量多的Go学习者可以轻松入门。
如果您觉得某些小节的内容您已掌握,可以跳过这部分直接做课后题。当然,您也可以
回过头来复习本小节。
## 课程
* **写下第一个Go程序**
* 请看所有的课程.
* Go文档是什么?
* "写一个库"之前的准备课程
* **掌握Go的类型系统**
* 每个Go类型都有一个零值
* blank标识符是什么?
* 让我们定义一组变量!
* 类型引用是什么?
* 怎样声明短变量?
* 为何不能在包中声明短变量?
* 重复声明是什么?
* 什么情况可以适合使用短变量声明?
* 学习从命令行获取输入和切片
* 学习 os.Args 基本用法
* 使用 os.Args 实现欢迎新人
* 使用Printf 进行格式化输出的准备工作
* 将摄氏度转换为华氏度
* 将换英尺转换为米
* 原始字符串是什么?
* 怎样获得字符串长度?
* 什么是预定义的类型之后的课程.
* 理解为定义类型的常量的后续课程, 章节的结束
* 学习常量的规则
* 复习: 常量
* 未定义类型的常量是怎样在钩子下运行的?
* 默认类型是什么?
* 例子: time.Duration
* iota 是什么?
* 推荐的命名法
* **控制Go的错误处理流程**
* 观看所有 "认证通过: 创建密码保护程序"之前的课程
* 观看所有 "理解Go的错误处理"之前的课程
* case 条件语句中使用多个值
* 回滚语句是怎样工作的?
* 解决方案: 一天的部分
* 复习: Switch 语句
* 怎样继续一个循环? (+奖励: 调试)
* 创建一个乘法表
* 怎样循环一个切片
* 范围: 轻巧地统计方法!
* **项目: 针对初学者**
* 请观看完整课程.
* **余下章节**
* 到目前为止,Go的基础部分已经结束。您可以观看余下的所有课程,余下课程覆盖了Go的高级特性.
## That's all! Enjoy! 🤩
---
# 奖励: 我们为什么要学Go?
**总结:** Go犹如Python和Javascript一样简单,C/C++一样快.使用Go作为工作语言会比C/C++更有趣。我们既可以使用Go的low-level API也可以使用high-level API。
## Go能用在哪些场景?
Go在互联网公司经常被应用,例如: Google, Facebook, Twitter, Uber, Apple, Dropbox, Soundcloud, Medium, Mozilla Firefox, Github, Docker, Kubernetes, 和 Heroku.
**Go 非常适合:** 跨平台命令行工具, 分布式网络系统, 微服务 和 Serverless, 网站APIs, 数据库引擎, 大数据处理流水线, 嵌入式开发, 等等.
**Go 不是特别适合 (但是可以使用):** 桌面应用, 操作系统, 内核驱动, 游戏开发, etc.
## Go的设计者是谁?
Go的设计者在工业界非常有影响力, 他们是:
* Unix: Ken Thompson
* UTF-8, Plan 9: Rob Pike
* Hotspot JVM (Java Virtual Machine): Robert Griesemer
## Go的市场薪资待遇
* [Go 薪资](https://www.payscale.com/research/US/Skill=Go_(Golang)_Programming_Language/Salary)
## [Go的前8年](https://blog.golang.org/8years):
> 如今, **每个云厂商的关键基础组件都可以看到Go语言的影子** 包括 Google Cloud, AWS, Microsoft Azure, Heroku, 等等. Go 是云厂商的重要部分.例如,Alibaba, Cloudflare, 和 Dropbox 都在使用Go. Go也是公共基础设施的重要组成部分。例如, Kubernetes, Cloud Foundry, Openshift, NATS, Docker, Istio, Etcd, Consul, Juju, 等都在使用Go. Companies are increasingly choosing Go,云基础设施方案选型中越来越多的公司开始采用Go.
## 我们可以用Go做哪些事情?
* [网络驱动程序](https://www.net.in.tum.de/fileadmin/bibtex/publications/theses/2018-ixy-go.pdf) (_与C驱动相比只有10%的性能差距_)
* [Google gVisor](https://cloud.google.com/blog/products/gcp/open-sourcing-gvisor-a-sandboxed-container-runtime) (_Go实现用户空间内核_)
* [多平台任天堂模拟器](https://humpheh.github.io/goboy/)
* [Docker: 容器](https://github.com/moby/moby)
* [Kubernetes: 容器编排管理](https://github.com/kubernetes/kubernetes)
* 虚拟机镜像处理工具
* 聊天服务器
* RUM beacon收集器
* 时间序列数据库引擎, 客户端, 命令行工具, 等等.
* Map-reduce依赖包
* 支持动态内容重写,图片放大缩放,缓存,Lua事件处理器功能的反向代理集群
* 基于地理位置的反向代理CDN节点
* 健康管理应用(时间处理&点对点报告)
* Go DNS 服务器
* 接入MySQL的API后台服务
* Linux 进程处理工具
* 作为反向代理隐藏后台服务器.
* HTML -> PDF 转换器.
* 短链接服务 类似 tinyurl.com 和 goo.gl
* SMS 消息服务.
* 信用卡支付网关
* JSON Web Token工具包
* 动态图像处理服务
* 第三方内容渲染工作流(十分庞大的项目)
* lxc 容器部署
* 自动化测试框架
参考: [This Reddit post](https://www.reddit.com/r/golang/comments/5nac2b/what_have_you_used_go_for_in_your_professional/).
## 更多Go相关请参考:
* [关于 Go: 概览](https://blog.learngoprogramming.com/about-go-language-an-overview-f0bee143597c)
* [为什么要学习Go?](https://medium.com/@kevalpatel2106/why-should-you-learn-go-f607681fad65)
* [云基础设施的新兴语言](https://redmonk.com/dberkholz/2014/03/18/go-the-emerging-language-of-cloud-infrastructure/)
* [使用Go的公司](https://github.com/golang/go/wiki/GoUsers)
* [Go的8年](https://blog.golang.org/8years)
* [Twitter: 使用Go一天处理50 亿会话](https://blog.twitter.com/engineering/en_us/a/2015/handling-five-billion-sessions-a-day-in-real-time.html)
* [C++工程师眼里的Go](https://www.murrayc.com/permalink/2017/06/26/a-c-developer-looks-at-go-the-programming-language-part-1-simple-features/)
> 更多内容: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2019 Inanc Gumus
>
> 学习Go编程课程
>
> [点击查看认证许可.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/chinese/02-编写第一个程序/README.md
================================================
# 备忘录: 编写第一个 GO 程序
嗨!
作为参考,你可以在参加本节讲座后保存这个备忘录
你也可以打印下来这个备忘录,然后和本节的视频讲座一起操作
加油!
---
## 命令行命令:
* 进入目录: `cd directoryPath`
* **WINDOWS:**
* 列出目录所有文件: `dir`
* **OS X & LINUXes:**
* 列出目录所有文件: `ls`
## 编译 & 运行 GO 程序:
* **编译一个 Go 程序:**
* 在程序所在目录,输入:
* `go build main.go`
* **运行一个 Go 程序:**
* 在程序所在目录,输入:
* `go run main.go`
## 你应该将源代码放在哪里?
* 你想放到哪个目录都可以
## 第一个程序
### 新建一个目录
* 新建一个目录:
* `mkdir myDirectoryName`
* 进入目录:
* `cd myDirectoryName`
### 添加源代码文件
* 新建源代码文件 `code main.go`
* 这条命令会在当前目录新建一个文件并使用 Visual Studio Code 打开该文件。
* 然后复制下面的代码到文件并保存文件
```go
package main
import "fmt"
func main() {
fmt.Println("Hi! I want to be a Gopher!")
}
```
### 运行程序
* 最后,返回到命令行
* 执行命令: `go run main.go`
* 如果你创建了其他文件并想同时执行它们,可以使用这个命令:
* `go run .`
这就是全部内容了!
> 更多资料, 参考: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2018 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/chinese/02-编写第一个程序/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// package main 是一个特殊的包
// 它允许 Go 创建一个可执行文件
package main
/*
这是一个多行注释
import 关键字引入另一个包
对于这个 .go ”文件“
import "fmt" 允许你使用 fmt 包的各种函数
在这个文件
*/
import "fmt"
// "func main" 是特殊的
//
// Go 必须知道从哪里开始执行
//
// func main 对于 Go 而言就是开始执行的位置
//
// 代码编译后,
// Go runtime 第一个执行该函数
func main() {
// import "fmt" 之后
// "fmt" 包中的 Println 函数就可以使用
// 在控制台输入下面的命令可以查看它的源代码:
// go doc -src fmt Println
// Println 是一个 exported 函数来自
// "fmt" 包
// Exported = 首字母大写
fmt.Println("Hello Gopher!")
// Go 本身不能调用 Println 函数
// 这就是为什么你需要在这里调用它
// Go 只能自动地调用 `func main`
// -----
// Go 字符串支持 Unicode 字符
// 源代码同时也支持: KÖSTEBEK!
//
// 因为: 字面值 ~= 源代码
// 练习: 删除下行注释的 --> //
// fmt.Println("Merhaba Köstebek!")
// 不重要的注释:
// "Merhaba Köstebek" 的意思是 "你好 Gopher"
// 在土耳其语
}
================================================
FILE: translation/chinese/02-编写第一个程序/带注释的 GO 程序.md
================================================
# 带注释的 Go 程序
```go
// package main 是一个特殊的包
// 它允许 Go 创建一个可执行文件
package main
/*
这是一个多行注释
import 关键字引入另一个包
对于这个 .go ”文件“
import "fmt" 允许你使用 fmt 包的各种函数
在这个文件
*/
import "fmt"
// "func main" 是特殊的
//
// Go 必须知道从哪里开始执行
//
// func main 对于 Go 而言就是开始执行的位置
//
// 代码编译后,
// Go runtime 第一个执行该函数
func main() {
// import "fmt" 之后
// "fmt" 包中的 Println 函数就可以使用
// 在控制台输入下面的命令可以查看它的源代码:
// go doc -src fmt Println
// Println 是一个 exported 函数来自
// "fmt" 包
// Exported = 首字母大写
fmt.Println("Hello Gopher!")
// Go 本身不能调用 Println 函数
// 这就是为什么你需要在这里调用它
// Go 只能自动地调用 `func main`
// -----
// Go 字符串支持 Unicode 字符
// 源代码同时也支持: KÖSTEBEK!
//
// 因为: 字面值 ~= 源代码
}
```
> 更多资料, 参考: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2018 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click here to read the license.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/chinese/02-编写第一个程序/练习/01-print-names/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: Print names
//
// 打印你和你最好朋友的名字使用
// Println 两次
//
// 练习输出
// 你的名字
// 你朋友的名字
//
// 额外任务
// 首先使用 `go run`
// 然后使用 `go build` 并运行你的程序
// ---------------------------------------------------------
func main() {
// ?
// ?
}
================================================
FILE: translation/chinese/02-编写第一个程序/练习/01-print-names/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// go run main.go
// go build
// ./solution
func main() {
fmt.Println("Nikola")
fmt.Println("Thomas")
}
================================================
FILE: translation/chinese/02-编写第一个程序/练习/README.md
================================================
1. **打印你和你最好朋友的名字** 使用 Println 两次。 [练习点击这里](https://github.com/inancgumus/learngo/tree/master/02-write-your-first-program/exercises/01-print-names).
2. **自娱自乐**
1. 使用 `go build` 编译程序
2. **发送程序给你的朋友**
他/她应该和你使用相同的操作系统
例如,如果你使用的是 Windows ,他/她应该也使用 Windows
3. **发送程序给你的朋友如果他使用不同的操作系统**
这样,你应该为他/她的操作系统编译程序
**编译 OSX 可执行程序:**
`GOOS=darwin GOARCH=386 go build`
**编译 Windows 可执行程序:**
`GOOS=windows GOARCH=386 go build`
**编译 Linux 可执行程序:**
`GOOS=linux GOARCH=arm GOARM=7 go build`
**通过这里可以获取全部列表:**
https://golang.org/doc/install/source#environment
**注意:** 如果你使用命令提示符或者 PowerShell , 你可能需要使用下面的命令:
`cmd /c "set GOOS=darwin GOARCH=386 && go build"`
3. **调用 [Print](https://golang.org/pkg/fmt/#Print) 而不是 [Println](https://golang.org/pkg/fmt/#Println)** 看看会发生什么
4. **调用 [Println](https://golang.org/pkg/fmt/#Println) 或者 [Print](https://golang.org/pkg/fmt/#Print) 输入多个数据** 通过逗号分隔
5. **移除字符串两边的双引号** 看看会发生什么
6. **将 package 和 import 声明** 移到文件末尾看看会发生什么
7. **[阅读 Go 在线文档](https://golang.org/pkg)**.
1. 快速浏览 packages ,看看它们的用途
2. 通过点击标题查看其源代码
3. 你不必弄懂全部,只需要亲自写吧,这仅仅是为了后面的课程热身
8. 对了, **打开 tour**: https://tour.golang.org/
1. 快速浏览一下,查看一下语言特点
2. 我们很快会讨论它们
9. [关注我的 twitter 学习更多](https://twitter.com/inancgumus).
================================================
FILE: translation/chinese/02-编写第一个程序/问题/01-gopath/README.md
================================================
## 应该保存 Go 源代码到哪里?
* 我的电脑任何地方
* $GOPATH 下
* $GOPATH/src 下 *正确*
## $GOPATH 是什么?
* 它是 Go 运行时的文件
* 存储 Go 源代码文件和编译的包的目录
* 它是 gophers 需要关注的地址
## 需不需要设置 $GOPATH?
* 需要
* 不需要: 它保存在我的电脑里面
* 不需要: 它保存在用户目录下 *正确*
## 如何打印 $GOPATH 的值?
* 使用 `ls` 命令
* 使用 `go env GOPATH` 命令 *正确*
* 使用 `go environment` 命令
================================================
FILE: translation/chinese/02-编写第一个程序/问题/02-code-your-first-program/README.md
================================================
## 下面哪一个关键字用来定义一个包?
```go
package main
func main() {
}
```
1. func
2. package *正确*
3. fmt.Println
4. import
> **1:** func 关键字用来新定义一个函数
>
>
> **2:** 对,package 关键字用来在 Go 文件中定义包
>
>
> **3:** 这不是关键字,它是 fmt 包中的一个函数
>
>
> **4:** import 关键字用来导入一个包
>
>
## 在下面代码中使用 package main 的目的是什么?
```go
package main
func main() {
}
```
* 为了创建一个库包
* 为了正确退出程序
* 为了创建一个可执行的 Go 程序 *正确*
## 在下面代码中使用 func main 的目的是什么?
```go
package main
func main() {
}
```
1. 为了创建一个叫 main 的包
2. 为了让 Go 开始执行程序 *正确*
3. 为了向控制台打印一条消息
> **1:** main function 不创建一个包
>
>
> **2:** 对,Go 自动地从 main 函数开始执行
>
>
> **3:** 它不会打印任何东西(目前为止)
>
>
## 在下面代码中使用 import "fmt" 的目的是什么?
```go
package main
import "fmt"
func main() {
fmt.Println("Hi!")
}
```
1. 它打印 "fmt" 到控制台
2. 它创建一个叫 "fmt" 的包
3. 它导入了 `fmt` 包; 这样你就可以使用其功能 *正确*
> **1:** `fmt.Println` 打印一条消息而不是 `import "fmt"`
>
>
> **2:** `package` 关键字创建新包,而不是 `import`
>
>
> **3:** 对,举个例子,导入 fmt 包后,你就可以使用 Println 打印一条消息到控制台
>
>
## 下面哪一个用来定义函数?
* func *正确*
* package
* Println
* import
## 函数是什么?
1. 它就像迷你程序,它是可复用可执行的代码块 *正确*
2. 它允许 Go 执行一个程序
3. 它允许 Go 导入一个叫 function 的包
4. 它打印一条消息到控制台
> **2:** Go 寻找 main 包的 func main 去执行,一个函数自己不能执行
>
>
> **3:** 这是 `import` 的作用
>
>
> **4:** 举个例子: 这是 `fmt.Println` 的功能
>
>
## 是否需要亲自调用 main 函数
1. 是的,只有这样才能运行自己的程序
2. 不必,Go 会自动地调用 main 函数 *正确*
> **1:** 不必, 不需要调用 main 函数, Go 自动执行它
>
>
## 是否需要调用一个函数去执行它?
_(main 函数除外)_
1. 需要,只有这样 Go 才能执行一个函数 *正确*
2. 需要,只有这样 Go 才执行程序
3. 不需要,函数会自动执行
> **1:** 对的,需要自己调用函数,Go 不会自动执行函数,只有 main 函数自动调用(还有其他一些函数,不过目前还未学到)
>
>
> **2:** 这是 `func main` 的唯一工作, 也只有 `func main` 才能执行程序
>
>
> **3:** Go 不会自动调用函数,除了 main 函数(还有其他一些函数,不过目前还未学到),所以,除了 main 函数,你需要手动调用函数
>
## 下面的程序输出是什么?
```go
package main
func main() {
}
```
1. 它打印一条消息到控制台
2. 它是正确的程序,但是什么都不输出 *正确*
3. 它不是正确的程序
> **1:** 它不是输出任何消息,可以使用 fmt.Println 函数来输出内容
>
>
> **2:** 对,它是正确的程序,然后因为它不包含 fmt.Println 所以它什么也不输出
>
>
> **3:** 它是正确的程序,它使用 package 关键字,并且有 main 函数。因此,这是一个有效且可执行的 Go 程序
>
>
## 这个程序的输出是什么?
```go
package main
func main() {
fmt.Println(Hi! I want to be a Gopher!)
}
```
* Hi! I want to be a Gopher!
* 它什么都不打印
* 它不是正确的程序 *正确*
> **1:** 没有用双引号括起来,Println 不能获取值,应该是: fmt.Println("Hi! I want to be a Gopher")
>
>
> **3:** 它没有导入 "fmt" 包, 还有 #1.
>
>
## 这个程序的输出是什么?
```go
package main
import "fmt"
func main() {
fmt.Println("Hi there!")
}
```
* Hi there! *正确*
* fmt
* 它不是正确的程序; 它导入的包里面没有函数叫 `Println`
> **2:** import "fmt" 导入 fmt 包,就可以使用其功能
>
>
> **3:** 实际上,这个程序是正确的
>
>
================================================
FILE: translation/chinese/02-编写第一个程序/问题/03-run-your-first-program/README.md
================================================
## `go build` 和 `go run` 有什么区别?
1. `go run` 只编译程序; 而 `go build` 编译运行程序
2. `go run` 编译运行程序; whereas `go build` 只编译程序。 *正确*
> **1:** 实际上相反的
>
>
> **2:** `go run` 编译程序并把它放在一个临时目录下,然后在临时目录里运行整个程序
>
>
## Go 保存编译后的代码在那个目录下?
1. 和执行 `go build` 相同的目录 *正确*
2. $GOPATH/src 目录
3. $GOPATH/pkg 目录
4. 进入一个临时目录
> **2:** 这里只有源代码文件
>
>
> **3:** 当你执行 `go install`,Go 将你的代码安装在这里
>
>
## 关于 runtime 哪个是正确的?
1. 它发生在开始运行程序时 *正确*
2. 它发生在编译程序时
## 关于 compile-time 哪个是正确的?
1. 它发生在开始运行程序时
2. 它发生在编译程序时 *正确*
## Go 程序什么时候打印一条信息到控制台?
1. 编译程序时
2. 程序运行时 (compile-time 之后) *正确*
3. 程序运行时 (和 compile-time 同时)
> **1:** 编译阶段,程序不能打印一条消息,因为它还没有被执行
>
>
> **2:** 对, 程序只有这时才会计算机互交,向控制台打印一条消息
>
>
> **3:** 程序只有编译之后才能运行
>
>
================================================
FILE: translation/chinese/03-包和作用域/01-packages/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("Bye!")
}
================================================
FILE: translation/chinese/03-包和作用域/01-packages/hey.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hey() {
fmt.Println("Hey!")
}
================================================
FILE: translation/chinese/03-包和作用域/01-packages/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
// 你可以使用其他文件的函数
// 只要它们在同一个包中
// 因此, `main()` 可以调用 `bye()` and `hey()`
// 因为 bye.go, hey.go 和 main.go
// 都在 main package 中
bye()
hey()
}
================================================
FILE: translation/chinese/03-包和作用域/02-scopes/01-scopes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// 文件作用域
import "fmt"
// 包作用域
const ok = true
// 包作用域
func main() { // 块作用域开始
var hello = "Hello"
// hello 和 ok 都可见
fmt.Println(hello, ok)
} // 块作用域结束
================================================
FILE: translation/chinese/03-包和作用域/02-scopes/02-block-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func nope() { //块作用域开始
// hello 和 ok 只定义在当前块作用域
const ok = true
var hello = "Hello"
_ = hello
} // 块作用域结束
func main() { // 块作用域开始
// hello 和 ok 不可见
// ERROR:
// fmt.Println(hello, ok)
} // 块作用域结束
================================================
FILE: translation/chinese/03-包和作用域/02-scopes/03-nested-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// 我不想在这节课中谈论这个话题
// 作为旁注,我想把它放在这里
// 记得复习
var declareMeAgain = 10
func nested() { // 块作用域开始
// 定义相同的变量
// 它们可以同时存在
// 这个只属于块作用域
// 包作用域的变量仍然可以使用
var declareMeAgain = 5
fmt.Println("inside nested:", declareMeAgain)
} // 块作用域结束
func main() { // 块作用域开始
fmt.Println("inside main:", declareMeAgain)
nested()
// 包作用域的 declareMeAgain 不受 nested 函数的影响
fmt.Println("inside main:", declareMeAgain)
} // 块作用域结束
================================================
FILE: translation/chinese/03-包和作用域/02-scopes/04-package-scope/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("Bye!")
}
================================================
FILE: translation/chinese/03-包和作用域/02-scopes/04-package-scope/hey.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hey() {
fmt.Println("Hey!")
}
================================================
FILE: translation/chinese/03-包和作用域/02-scopes/04-package-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
// 两个文件属于同一个包
// 在这里调用 bye.go 的 `bye()`
bye()
}
// 练习: 删除下面函数的注释
// 分析错误信息
// func bye() {
// fmt.Println("Bye!")
// }
// ***** EXPLANATION *****
//
// ERROR: "bye" function "redeclared"
// in "this block"
//
// "this block" 是指 = "main package"
//
// "redeclared" 是指在同一个作用域中使用了相同的名字
//
// main package's 作用域是:
// main 包中的所有源代码文件
================================================
FILE: translation/chinese/03-包和作用域/03-importing/01-file-scope/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// 取消下面代码的注释会出错
// (只删除最后三行的 //)
// 这个文件看不到 main.go's 导入的 ("fmt")的名字
// 因为导入的名字在文件作用域
// func bye() {
// fmt.Println("Bye!")
// }
================================================
FILE: translation/chinese/03-包和作用域/03-importing/01-file-scope/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
}
================================================
FILE: translation/chinese/03-包和作用域/03-importing/02-renaming/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
import f "fmt"
func main() {
fmt.Println("Hello!")
f.Println("There!")
}
================================================
FILE: translation/chinese/03-包和作用域/练习/01-packages/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 使用自己定义的包
//
// 创建几个 Go 文件,并在 main 函数里调用它们里面的函数
//
// 1- 创建 main.go, greet.go 和 bye.go 文件
// 2- 在 main.go 中: 调用 greet 和 bye 函数
// 3- 运行 `main.go`
//
// 提升
// greet 函数定义在 greet.go
// bye 定义在 bye.go
//
// 目标输出
// hi there
// goodbye
// ---------------------------------------------------------
func main() {
// 在这里调用其他文件的函数
}
================================================
FILE: translation/chinese/03-包和作用域/练习/01-packages/solution/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("goodbye")
}
================================================
FILE: translation/chinese/03-包和作用域/练习/01-packages/solution/greet.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func greet() {
fmt.Println("hi there")
}
================================================
FILE: translation/chinese/03-包和作用域/练习/01-packages/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
greet()
bye()
}
================================================
FILE: translation/chinese/03-包和作用域/练习/02-scopes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 作用域的初体验
//
// 1. 创建两个文件: main.go 和 printer.go
//
// 2. 在 printer.go 中:
// 1. 创建一个叫 hello 的函数
// 2. hello 函数的作用是输出你的名字
//
// 3. 在 main.go 中:
// 1. 和之前一样,创建 main 函数
// 2. 调用你定义的函数,通过函数名 : hello
// 3. 创建一个叫 bye 的函数
// 4. 在 bye 函数中, 输出 "bye bye"
//
// 4. 在 printer.go 中:
// 1. 在 hello 函数中
// 调用 bye 函数
// ---------------------------------------------------------
func main() {
}
================================================
FILE: translation/chinese/03-包和作用域/练习/02-scopes/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// as you can see, I don't need to import a package
// and I can call `hello` function here.
//
// this is because, package-scoped names
// are shared in the same package
hello()
// but here, I can't access the fmt package without
// importing it.
//
// this is because, it's in the printer.go's file scope.
// it imports it.
// this main func can also call bye function here
// bye()
}
// printer.go can call this function
//
// this is because, bye function is in the package-scope
// of the main package now.
//
// main func can also call this.
func bye() {
fmt.Println("bye bye")
}
================================================
FILE: translation/chinese/03-包和作用域/练习/02-scopes/solution/printer.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hello() {
// only this file can access the imported fmt package
// when others also do so, they can also access
// their own `fmt` "name"
fmt.Println("hi! this is inanc!")
bye()
}
================================================
FILE: translation/chinese/03-包和作用域/练习/03-importing/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: imports 重命名
//
// 1- 使用不同的名字导入 fmt 包三次
//
// 2- 使用它们输出一些消息
//
// 目标输出
// hello
// hey
// hi
// ---------------------------------------------------------
// ?
// ?
// ?
func main() {
// ?
// ?
// ?
}
================================================
FILE: translation/chinese/03-包和作用域/练习/03-importing/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
import f "fmt"
import fm "fmt"
func main() {
fmt.Println("hello")
f.Println("hey")
fm.Println("hi")
}
================================================
FILE: translation/chinese/03-包和作用域/练习/README.md
================================================
1. **[使用自己定义的包](https://github.com/inancgumus/learngo/tree/master/03-packages-and-scopes/exercises/01-packages)**
创建几个 Go 文件,并在 main 函数里调用它们里面的函数
2. **[作用域的初体验](https://github.com/inancgumus/learngo/tree/master/03-packages-and-scopes/exercises/02-scopes)**
了解跨包作用域的效果
3. **[imports 重命名](https://github.com/inancgumus/learngo/tree/master/03-packages-and-scopes/exercises/03-importing)**
使用不同的名字导入同一个包
================================================
FILE: translation/chinese/03-包和作用域/问题/01-packages-A/README.md
================================================
## 属于同一个包的源代码存储在哪里?
1. 每个文件应该存储在不同的目录
2. 在同一个目录下 *正确*
## 为什么 Go 源代码需要使用 package 语句?
1. 用来导入包
2. 用来让 Go 知道该文件属于哪个包 *正确*
3. 用来声明新函数
> **1:** `import` 语句的作用.
>
>
> **3:** `func` 语句的作用
>
>
## `package clause` 需要写在 Go 源文件的哪里?
1. 写在 Go 源文件的开头 *正确*
2. 写在 Go 源文件的末尾
3. 写哪里都可以
## 一个 Go 源文件使用 `package clause` 几次
1. 一次 *正确*
2. 零次
3. 多次
## 下面哪一个正确使用 `package clause`?
1. `my package`
2. `package main`
3. `pkg main`
## 哪一个说法是正确?
1. 在同一个包下的文件不能调用其他文件定义的函数
2. 在同一个包下的文件可以调用其他文件定义的函数 *正确*
## 如何运行多个 Go 源代码
1. go run *.*go
2. go build *go
3. go run go
4. go run *.go *正确*
> **4:** 也可以是 (假设目录下有 file1.go file2.go 和 file3.go): go run file1.go file2.go file3.go
>
>
================================================
FILE: translation/chinese/03-包和作用域/问题/02-packages-B/README.md
================================================
## 下面哪一个是 Go 中正确的软件包类型?
* Empty package
* Executable package *正确*
* Transferrable package
* Librarian package
## 下面哪一个 package `go run` 可以执行?
* Empty package
* Executable package *正确*
* Transferrable package
* Library package
## 下面哪个 package `go build` 可以编译
* Empty package
* Temporary package
* Both of executable and library packages *正确*
* Transferrable package
## 下面哪一个是可执行的包
* 有 `func main` 的 `package main` *正确*
* 有 `func Main` 的 `package Main`
* 有 `func exec` 的 `package exec`
## 哪一个是 library package?
* `main package`
* `package lib` *正确*
* `func package`
* `package main` 有 `func main`
## 下面哪个包用于可执行 Go 程序?
* Empty package
* Executable package *正确*
* Transferrable package
* Library package
## 哪个包用于可重用并可以导入?
* Empty package
* Executable package
* Transferrable package
* Library package *正确*
================================================
FILE: translation/chinese/03-包和作用域/问题/03-scopes/README.md
================================================
## 作用域是什么?
* 可执行的代码块
* 声明变量的可见性 **正确**
* 确定要运行的内容
```go
package awesome
import "fmt"
var enabled bool
func block() {
var counter int
fmt.Println(counter)
}
```
## 哪个变量属于包作用域
1. awesome
2. fmt
3. enabled **正确**
4. counter
> **3:** 是的, `enabled` 在任何函数之外,所以它是包作用域的变量 `block()` 也是包作用域,它也在任何函数之外
>
>
## 哪一个变量属于文件作用域?
1. awesome
2. fmt **正确**
3. enabled
4. block()
5. counter
> **2:** 没错,导入的包名称属于文件作用域,而且它们只能在同一文件中使用。
>
>
## 哪一个在 block() 函数的作用域?
1. awesome
2. fmt
3. enabled
4. block()
5. counter **正确**
> **5:** 是的, `counter` 在 `block()` 函数内部定义,所以它属于函数作用域,对 `block()` 函数外的其他代码不可见
>
>
## `block()` 函数可以看见 `enabled` 变量吗?
1. 可以: 它在包作用域里 **正确**
2. 不可以: 它在文件作用域里
3. 不可以: 它在 block() 函数作用域里
> **1:** 包作用域的变量对同一个包下所有代码都可见
>
>
## `awesome`中的其他文件可以看见 `counter` 变量吗?
1. 可以
2. 不可以: 它在包作用域里
3. 不可以: 它在文件作用域里
4. 不可以: 它在 block() 函数的作用域里 **正确**
> **4:** 没错。其他代码都无法看到 `block()` 函数内部的变量。只有在 `block()` 函数内部的代码才能看到它们 (近在一定程度上 ,例如:函数内部的代码只能看到在它们之前声明的变量)
>
>
## `awesome` 中的其他文件可以看见 `fmt` 变量吗?
1. 可以
2. 不可以: 它在包作用域里
3. 不可以: 它在文件作用域里 **正确**
4. 不可以: 它在 block() 函数的作用域里
> **3:** 只有在 import 只定义在同一个文件内,不管是不是同一个包,其他文件都不可见
>
>
## 如果在相同的作用域中声明相同的变量会发生什么?
```go
package awesome
import "fmt"
// 在包作用域中声明两次
var enabled bool
var enabled bool
func block() {
var counter int
fmt.Println(counter)
}
```
1. 新声明的变量将覆盖前一个变量
2. 不能这样做,它已经在包作用域中声明了 *正确*
3. 不能这样做,它已经在文件作用域中声明了
> **2:** 没错,不能在同一个作用域内声明同一个变量,如果这样做,使用变量时获取的是前一个还是后一个声明的变量?
>
>
## 如果在不同的作用域中声明相同的变量会发生什么?
```go
package awesome
import "fmt"
// 在包作用域中声明
var enabled bool
func block() {
// 在函数作用域中声明
var enabled bool
var counter int
fmt.Println(counter)
}
```
1. 新声明的变量将覆盖前一个变量 *正确*
2. 不能这样做,它已经在包作用域中声明了
3. 不能这样做,它已经在文件作用域中声明了
> **1:** 实际上,可以在内部作用域中声明相同的变量,例如 `block()`'的作用域在包作用域里面。这意味这它可以获取到包作用域的变量(反之则不同). 所以, `block()`'作用域在包作用域之内。这意味着你可以再次声明相同的变量。它会覆盖掉父作用域的变量,它们同时存在,请查看课程存储库中的示例以找出答案。
>
>
================================================
FILE: translation/chinese/04-语句-表达式-注释/01-statements/01-execution-flow/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello!")
// 语句改变执行顺序
// 特别是流程控制语句,如 `if`
if 5 > 1 {
fmt.Println("bigger")
}
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/01-statements/02-semicolons/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello"); fmt.Println("World!")
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/02-expressions/01-operator/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello!" + "!")
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/02-expressions/02-call-expression/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"runtime"
)
func main() {
// runtime.NumCPU() 是一个调用表达式
fmt.Println(runtime.NumCPU() + 1)
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/03-comments/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// Package main makes this package an executable program
package main
import "fmt"
/*
main 函数
Go 通过这个函数执行这个程序
在 main package 有且只有一个 main 函数
可执行程序也可以称为 `commands`
*/
func main() {
fmt.Println("Hello Gopher!")
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/01-shy-semicolons/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 害羞的分号
//
// 1. 尝试使用分号来分隔表达式
//
//
// 2. 观察 Go 如何修复它们
//
// ---------------------------------------------------------
func main() {
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/01-shy-semicolons/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// 取消下面代码行的注释,然后保存文件。
//
// 可以看到 Gofmt 工具将自动格式化代码。
// https://golang.org/cmd/gofmt/
//
// 这是因为,Go 语言并不关心
// 在语句之间是否使用分号
//
// 毕竟,它会自动添加它们
/*
fmt.Println("inanc"); fmt.Println("lina"); fmt.Println("ebru");
*/
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/02-naked-expression/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 裸表达式
//
// 1. 尝试单独输入 "Hello" 在一行
// 2. 不要使用 Println
// 3. 查看错误
//
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/02-naked-expression/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// 取消下面一行的代码的注释,以查看错误。
/*
"Hello"
*/
// 会显示: "evaluted but not used"
//
// 因为:
// "Hello" 字面值返回了一个值但是
// 没有语句使用它
//
// 因此:
// 不能单独使用表达式而不使用语句
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/03-operators-combine/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 运算符组合表达式
//
// 输出下面的期待的输出结果
// 使用字符串连接运算符
//
// 提示
// 使用 + 运算符多次来组成 "Hello!!!?".
//
// EXPECTED OUTPUT
// "Hello!!!?"
// ---------------------------------------------------------
func main() {
// fmt.Println("Hello!" + ?)
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/03-operators-combine/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// 操作符可以将多个表达式
// 连接成一个表达式
fmt.Println("Hello!" + "!" + "!" + "?")
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/04-print-go-version/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 打印 Go 版本号
//
// 1. 查看 runtime 包的文档
// 2. 寻找返回 Go 版本号的函数
// 3. 打印 Go 版本号通过调用这个函数
//
// 提示
// 文档地址: https://golang.org/pkg/runtime
//
// 期待输出
// "go1.10"
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/04-print-go-version/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println(runtime.Version())
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/05-comment-out/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// 练习: 注释掉它
//
// 使用单行注释和多行注释注释掉下面的输出
//
// 期待输出
// 没有输出
// ---------------------------------------------------------
func main() {
fmt.Println("hello")
fmt.Println("how")
fmt.Println("are")
fmt.Println("you")
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/05-comment-out/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// fmt.Println("hello")
/*
fmt.Println("how")
fmt.Println("are")
fmt.Println("you")
*/
}
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/06-use-godoc/exercise.md
================================================
## 练习
- 在命令行中打印 `runtime.NumCPU` 函数的文档
- 在命令行中打印 `runtime.NumCPU` 函数的源码
## 提示
需要正确使用 `go doc` 工具
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/06-use-godoc/solution/solution.md
================================================
## 文档:
go doc runtime NumCPU
## 源代码:
go doc -src runtime NumCPU
================================================
FILE: translation/chinese/04-语句-表达式-注释/练习/README.md
================================================
1. **[害羞的分号](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/01-shy-semicolons)**
观察 Go 是怎么处理分号
2. **[裸表达式](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/02-naked-expression)**
观察使用不带语句的表达式时发生的情况
3. **[运算符组合表达式](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/03-operators-combine)**
使用运算符组合表达式
4. **[打印 Go 版本号](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/04-print-go-version)**
使用 Go 标准库中的软件包打印当前系统(当前运行 Go 程序的系统)安装的 Go 版本号
5. **[注释掉它](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/05-comment-out)**
了解如何注释代码
6. **[使用 GoDoc](https://github.com/inancgumus/learngo/tree/master/04-statements-expressions-comments/exercises/06-use-godoc)**
尝试使用 Godoc
================================================
FILE: translation/chinese/04-语句-表达式-注释/问题/01-statements/README.md
================================================
## 下面关于语句的描述哪个是正确的?
1. 一个语句指示 Go 执行某些操作 *正确*
2. 一个语句产生一个值
3. 一个语句无法改变执行流
> **2:** 一个语句不能产生一个值,但它可以间接的帮助产生一个值
>
>
> **3:** 不,它可以
>
>
## 下面关于 Go 代码的执行顺序哪个是正确的?
1. 从左到右
2. 从上到下 *正确*
3. 从右到左
4. 从下到上
> **2:** 是的,Go 的执行顺序是从上到下,一次一个语句
>
>
## 下面关于表达式的描述哪个是正确的?
1. 表达式指示 Go 执行某些操作
2. 一个表达式产生一个值 *正确*
3. 表达式可以改变执行流
> **1:** 不,语句可以
>
>
> **3:** 不,只有语句可以
>
>
## 下面关于运算符的描述哪个是正确的?
1. 运算符指示 Go 执行某些操作
2. 运算符可以改变执行流
3. 运算符可以组合表达式 *正确*
> **1:** 不,语句可以
>
>
> **2:** 不,只有语句可以
>
>
## 下面的程序为什么不起作用?
```go
package main
import "fmt"
func main() {
"Hello"
}
```
1. "Hello"是一个表达式,它不能没有语句单独在一行 *正确*
2. 去掉 “Hello” 的双引号,像这样: Hello
3. 将 "Hello" 移到 main 函数外面
## 下面的程序可以运行吗?
```go
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println(runtime.NumCPU()); fmt.Println("cpus"); fmt.Println("the machine")
}
```
1. 可以运行: 可以用分号来分隔表达式
2. 不能运行: 只能一行一个语句
3. 可以运行: Go 会自动地在每条语句的后面添加分号 *正确*
> **1:** 它可以运行,但不是这个原因,另外,表达式不能这样做
>
>
> **2:** 确定吗?
>
>
> **3:** 是的,无论是否有分号,Go 会自动的添加分号. 这些语句还是认为自己在不同的一行中
>
>
## 为什么下面的代码可以运行
```go
package main
import (
"fmt"
"runtime"
)
func main() {
fmt.Println(runtime.NumCPU() + 10)
}
```
1. 运算符可以组合表达式 *正确*
2. 语句可以和表达式一起使用
3. 表达式可以返回多值
> **1:** 是的, + 运算可以组合 `runtime.NumCPU()` 和 `10` 表达式
>
>
> **2:** 不对,不可以组合使用。例如,不能这样做:`import "fmt" + 3`. 一些语句需要表达式,但这不意味着语句和表达式可以组合使用
>
>
> **3:** 对的,但不能解释上面代码为什么可以运行
>
>
================================================
FILE: translation/chinese/04-语句-表达式-注释/问题/02-expressions/README.md
================================================
## 请查看 statements 目录下的问题
================================================
FILE: translation/chinese/04-语句-表达式-注释/问题/03-comments/README.md
================================================
## 为什么有时需要用到注释?
1. 为了将不同的表达式组合起来
2. 为了给代码提供说明或者自动生成文档 *正确*
3. 为了让代码看起来更漂亮
## 下面的代码哪个是正确的?
1.
```go
package main
/ main function is an entry point /
func main() {
fmt.Println("Hi")
}
```
2. *正确*
```go
package main
// main function is an entry point /*
func main() {
fmt.Println(/* this will print Hi! */ "Hi")
}
```
3.
```go
package main
/*
main function is an entry point
It allows Go to find where to start executing an executable program.
*/
func main() {
fmt.Println(// "this will print Hi!")
}
```
> **1:** `/` 不是注释,单行注释是 `//`.
>
>
> **2:** 多行注释可以放在任何位置。但是,当有一个以 `/*`开头的注释,需要以 `*/` 结尾。 这里,Go 不关心 `/* ... */` 里面的内容, 它直接跳过。同时,Go 看到以 `//` 开头的代码,直接跳过整行代码。
>
>
> **3:** `//` 阻止 Go 解析后面的内容,这就是它不能运行的原因, Go 不能解析 `"this will print Hi!")` 因为它们是注释。
>
>
## 应该如何命名代码,以便 Go 可以从代码自动生成文档?
1. 通过注释的每一行代码,这样就会自动生成文档
2. 通过在声明变量后开始进行注释 *正确*
3. 通过使用多行注释
> **1:** 对不起,这没用
>
>
> **3:** 它不关心使用单行注释还是多行注释
>
>
## 在命令行打印文档需要用到下面哪个?
1. go build
2. go run
3. go doctor
4. go doc *正确*
## `godoc` 和 `go doc` 有什么不同?
1. `go doc` 是 `godoc` 背后真实的工具
2. `godoc` 是 `go doc` 背后真实的工具 *正确*
3. `go` 是 `go doc` 背后真实的工具
4. `go` 是 `godoc` 背后真实的工具
> **2:** 是的, go doc 背后使用 godoc, go doc 只是简单版本的 godoc
>
>
================================================
FILE: translation/chinese/05-编写你的第一个库程序包/printer/cmd/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// 自动导入!... 好耶!
import "github.com/inancgumus/learngo/05-write-your-first-library-package/printer"
func main() {
printer.Hello()
}
================================================
FILE: translation/chinese/05-编写你的第一个库程序包/printer/printer.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package printer
import "fmt"
// Hello 是一个导出函数
func Hello() {
fmt.Println("exported hello")
}
================================================
FILE: translation/chinese/05-编写你的第一个库程序包/练习/README.md
================================================
[Check out the exercise and its solution here.](https://github.com/inancgumus/learngo/tree/master/05-write-your-first-library-package/exercise)
---
# 练习
1. 新建一个库
2. 在库中,创建一个返回 Go 版本的函数。
3. 创建一个可执行程序并导入你的库
4. 调用你创建的返回 Go 版本的函数
5. 执行你的程序
## 提示
**像这样创建你的包函数:**
```go
func Version() string {
return runtime.Version()
}
```
## 期望输出
他应该打印出你系统安装的 Go 的版本
## 警告
你应该在你自己的文件夹下创建这个包,而不是在 github.com/inancgumus/learngo 目录下。同时,注意 VS Code 可能会自动导入我位于 github.com/inancgumus/learngo 的库而非你自己的库。
所以,如果你想要 VS Code 自动在保存时导入你自己的包,只需要将 github.com/inancgumus/learngo 移动到非 GOPATH 的某处,比如,你的桌面(记得在之后移动回来)
See [this question](https://www.udemy.com/learn-go-the-complete-bootcamp-course-golang/learn/v4/questions/5518190) in Q&A for more information.
================================================
FILE: translation/chinese/05-编写你的第一个库程序包/练习/solution/golang/cmd/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt" // 你应该将这里替换成你自己的用户名
"github.com/inancgumus/learngo/05-write-your-first-library-package/exercise/solution/golang"
)
func main() {
fmt.Println(golang.Version())
}
================================================
FILE: translation/chinese/05-编写你的第一个库程序包/练习/solution/golang/go.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package golang
import (
"runtime"
)
// Version 返回当前的 Go 版本
func Version() string {
return runtime.Version()
}
================================================
FILE: translation/chinese/05-编写你的第一个库程序包/问题/README.md
================================================
## 下面哪一个是正确的?
**注意** _答案当中含有解释。即便你已经知道答案,也请逐一选择每个选项,这样可以阅读到解释。_
1. 你可以运行一个库程序包。
2. 在一个库程序包中,应该含有一个叫做 main 的函数 (func main)。
3. 你可以编译一个库程序包。*正确*
4. 你必须编译一个库程序包。
> **1:** 你不能运行,但你可以从其他包中导入它。
>
> **2:** 在一个库程序包中,没有必要包含 main 函数。因为它并非一个可执行的包。只有在可执行的包中才需要 main 函数。
>
> **4:** 你没有必要编译它。当你导入它时,它会自动在编译或运行时被其他程序或库构建。
## 在导出名称时你需要做什么?
1. 你需要将名称全部大写
2. 你需要将名称的首字母大写 *正确*
3. 你需要把名称放到一个函数作用域里
4. 你需要用这个名称创建一个新的文件
> **1:** 当你这样做时,它的确会被导出,但不要这样做;因此我认为这个答案不正确 :)
>
> **2:** 正确的。这样做之后其他包便可以访问它。
>
> **3:** 它应该在包作用域内,而不是函数作用域内。
>
> **4:** 没必要这样做。
## 你要怎么在一个可执行程序中使用一个你的库中的函数呢?
1. 你需要首先导出你的库程序包;然后你可以访问它的导入名称
2. 你需要首先导入你的库程序包;然后你可以访问它的导出名称 *正确*
3. 你可以像它本来就在你的可执行程序中一样,访问你的库程序包
4. 你可以通过使用它的名称来导入它
> **1:** 你不能导出包。所有的包都是已经导出的。除非你将它们放到一个叫做 "internal" 的目录中。但是,这是一个对于现在过于进阶的话题。
>
> **2:** 正确的。
>
> **3:** 你不能在不导入的情况下,在一个包中访问另一个包。
>
> **4:** 你不能这么做。你需要在 GOPATH 后使用完整的路径来导入它。顺带一提,在不久的将来,这可能会随着 Go 模块的支持而改变。
## 在下面的程序中,哪些名称被导出了?
```go
package wizard
import "fmt"
func doMagic() {
fmt.Println("enchanted!")
}
func Fireball() {
fmt.Println("fireball!!!")
}
```
1. fmt
2. doMagic
3. Fireball *正确*
4. Println
> **1:** 这是导入包的名称。
>
> **2:** 它以小写字母开头;所以,它没有被导出。
>
> **3:** 正确的。它以大写字母开头。
>
> **4:** 这不是你写的函数。它已经在 fmt 包中被导出了。但它没有在这里被导出。
## 在下面的程序中,哪些名称被导出了?
```go
package wizard
import "fmt"
var one string
var Two string
var greenTrees string
func doMagic() {
fmt.Println("enchanted!")
}
func Fireball() {
fmt.Println("fireball!!!")
}
```
1. doMagic 和 Fireball
2. Fireball 和 Two *CORRECT*
3. Fireball, greenTrees 和 Two
4. Fireball, greenTrees, one 和 Two
> **1:** doMagic 以小写字母开头;所以没有被导出。
>
> **2:** 正确的。Fireball 和 Two 都以大写字母开头。
>
> **3:** greenTrees 以小写字母开头;所以没有被导出。
>
> **4:** one 和 greenTrees 没有以大写字母开头;所以没有被导出。
================================================
FILE: translation/chinese/06-变量/01-基础数据类型/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// 整数型
fmt.Println(
-200, -100, 0, 50, 100, 100,
)
// 浮点型
fmt.Println(
-50.5, -20.5, -0., 1., 100.56, // ...
)
// 布尔值
fmt.Println(
true, false,
)
// 字符串 - utf-8
fmt.Println(
"", // 空字符串, 只打印一个空格
"hi",
// unicode
"nasılsın?", // 土耳其语的 "你好吗"
"hi there 星!", // "你好,star!"
)
}
================================================
FILE: translation/chinese/06-变量/01-基础数据类型/练习/01-print-the-literals/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 打印字面量
//
// 1. 打印一些整数型
//
// 2. 打印一些浮点型
//
// 3. 打印 true 和 false 的布尔值
//
// 4. 用字符串打印你的名字
//
// 5. 用字符串打印一句非英文的句子
//
// ---------------------------------------------------------
func main() {
// 使用 fmt.Println()
}
================================================
FILE: translation/chinese/06-变量/01-基础数据类型/练习/01-print-the-literals/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println(42, 8500, 344433, -2323)
fmt.Println(3.14, 6.28, -42.)
fmt.Println(true, false)
fmt.Println("Hi! I'm Inanc!")
fmt.Println("Merhaba, adım İnanç!")
}
================================================
FILE: translation/chinese/06-变量/01-基础数据类型/练习/02-print-hexes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// 这个练习是可选的
// ---------------------------------------------------------
// 练习: 打印十六进制
//
// 1. 打印十六进制的 0 到 9
//
// 2. 打印十六进制的 10 到 15
//
// 3. 打印十六进制的 17
//
// 4. 打印十六进制的 25
//
// 5. P打印十六进制的 50
//
// 6. 打印十六进制的 100
//
// 期望输出
// 0 1 2 3 4 5 6 7 8 9
// 10 11 12 13 14 15
// 17
// 25
// 50
// 100
//
// NOTE
// https://stackoverflow.com/questions/910309/how-to-turn-hexadecimal-into-decimal-using-brain
//
// https://simple.wikipedia.org/wiki/Hexadecimal_numeral_system
//
// ---------------------------------------------------------
func main() {
// 例子
// 我要打印十六进制的 10
fmt.Println(0xa)
// 我要打印十六进制的 16
// 0x10
// ^^----- 1 * 0 = 0
// |
// +------ 16 * 1 = 16
// = 16
fmt.Println(0x10)
// 我要打印十六进制的 150
// 0x96
// ^^----- 1 * 6 = 6
// |
// +------ 16 * 9 = 144
// = 150
fmt.Println(0x96)
// 把上面的所有代码注释掉, 然后
// 在下面写下你的代码
}
================================================
FILE: translation/chinese/06-变量/01-基础数据类型/练习/02-print-hexes/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println(0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9)
fmt.Println(0xa, 0xb, 0xc, 0xd, 0xe, 0xf)
fmt.Println(0x11) // 17
fmt.Println(0x19) // 25
fmt.Println(0x32) // 50
fmt.Println(0x64) // 100
}
================================================
FILE: translation/chinese/06-变量/01-基础数据类型/练习/README.md
================================================
1. **[打印字面量](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/01-基础数据类型/练习/01-print-the-literals)**
使用字面量打印一些值
2. **[打印十六进制数](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/01-基础数据类型/练习/02-print-hexes)** (可选练习)
打印十六进制的数
================================================
FILE: translation/chinese/06-变量/01-基础数据类型/问题/README.md
================================================
## 下面哪个是整数型 (int)?
* -42 *正确*
* 这是整数型
* "Hello"
* 这是字符串
* false
* 这是布尔值
* 3.14
* 这是浮点型
## 下面哪个是浮点型 (float)?
* -42
* "Hello"
* false
* 3.14 *正确*
## 下面哪个是浮点型 (float)?
* 6,28
* ,28
* .28 *正确*
* 628
## 下面哪个是字符串 (string)?
* -42
* "Hello" *正确*
* false
* 3.14
## 下面哪个是布尔值 (bool)?
* -42
* "Hello"
* false *正确*
* 3.14
================================================
FILE: translation/chinese/06-变量/02-声明/01-声明语法/01-语法/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var speed int
fmt.Println(speed)
}
================================================
FILE: translation/chinese/06-变量/02-声明/01-声明语法/02-命名规则/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// 变量声明规则
func main() {
// 正确的声明
var speed int
var SpeeD int
// 下划线开头是允许但不推荐的
var _speed int
// Unicode 字母是允许的
var 速度 int
// 让编译器开心
_, _, _, _ = speed, SpeeD, _speed, 速度
}
================================================
FILE: translation/chinese/06-变量/02-声明/01-声明语法/03-声明顺序/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// fmt.Println(speed)
// var speed int
}
================================================
FILE: translation/chinese/06-变量/02-声明/02-声明示例/01-int/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var nFiles int
var counter int
var nCPU int
fmt.Println(
nFiles,
counter,
nCPU,
)
}
================================================
FILE: translation/chinese/06-变量/02-声明/02-声明示例/02-float64/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var heat float64
var ratio float64
var degree float64
fmt.Println(
heat,
ratio,
degree,
)
}
================================================
FILE: translation/chinese/06-变量/02-声明/02-声明示例/03-bool/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var off bool
var valid bool
var closed bool
fmt.Println(
off,
valid,
closed,
)
}
================================================
FILE: translation/chinese/06-变量/02-声明/02-声明示例/04-string/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var msg string
var name string
var text string
fmt.Println(
msg,
name,
text,
)
}
================================================
FILE: translation/chinese/06-变量/02-声明/03-零值/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// 练习: 运行这个, 然后自己查看这些零值 (这里的 零值 指的是变量未初始化时的值, 根据类型的不同会有不同的结果, 而非字面意义上的 "0")
func main() {
var speed int // 数字类型
var heat float64 // 数字类型
var off bool
var brand string
fmt.Println(speed)
fmt.Println(heat)
fmt.Println(off)
// 我用 Printf 来打印空字符串
// 练习: 用 Println 看看会发生什么
fmt.Printf("%q\n", brand)
}
================================================
FILE: translation/chinese/06-变量/02-声明/04-未使用的变量和空白标识符/01-未使用的变量/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// 对包级变量没有警告
var packageLevelVar string
func main() {
// 未使用变量错误
// var speed int
// 如果你使用了它, 错误就会消失
// fmt.Println(speed)
}
================================================
FILE: translation/chinese/06-变量/02-声明/04-未使用的变量和空白标识符/02-空白标识符/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
var speed int
// 让我们把变量赋值给空白标识符
// 这样,Go编译器就不会发脾气了
_ = speed
}
================================================
FILE: translation/chinese/06-变量/02-声明/05-多重声明/01-多重声明/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
speed int
heat float64
off bool
brand string
)
fmt.Println(speed)
fmt.Println(heat)
fmt.Println(off)
fmt.Printf("%q\n", brand)
}
================================================
FILE: translation/chinese/06-变量/02-声明/05-多重声明/02-平行声明/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// 这等同于
//
// var (
// speed int
// velocity int
// )
//
// 或者:
//
// var speed int
// var velocity int
//
var speed, velocity int
fmt.Println(speed, velocity)
}
================================================
FILE: translation/chinese/06-变量/02-声明/06-例子/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// 变量名是大小写敏感的
// MyAge, myAge 和 MYAGE 是不同的变量
// 使用例:
// 什么时候使用平行声明?
//
// 不好:
// var myAge int
// var yourAge int
//
// 一般:
// var (
// myAge int
// yourAge int
// )
//
// 推荐:
var myAge, yourAge int
fmt.Println(myAge, yourAge)
var temperature float64
fmt.Println(temperature)
var success bool
fmt.Println(success)
var language string
fmt.Println(language)
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/01-int/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 声明 int
//
// 1. 声明并打印一个 int 型变量
//
// 2. 变量名应该叫做: height
//
// 期望输出
// 0
// ---------------------------------------------------------
func main() {
// var ? ?
// ?
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/01-int/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var height int
fmt.Println(height)
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/02-bool/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 声明 bool
//
// 1. 声明并打印一个 bool 型变量
//
// 2. 变量名应该叫做: isOn
//
// 期望输出
// false
// ---------------------------------------------------------
func main() {
// var ? ?
// ?
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/02-bool/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var isOn bool
fmt.Println(isOn)
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/03-float64/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 声明 float64
//
// 1. 声明并打印一个 float64 型变量
//
// 2. 变量名应该叫做: brightness
//
// 期望输出
// 0
// ---------------------------------------------------------
func main() {
// var ? ?
// ?
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/03-float64/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
var brightness float64
fmt.Println(brightness)
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/04-string/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 声明 string
//
// 1. 声明一个 string 型变量
//
// 2. 打印这个变量
//
// 期望输出
// ""
// ---------------------------------------------------------
func main() {
// 使用下面的代码
// 你会在之后学习到 Printf 函数
// var ?
// fmt.Printf("s (%T): %q\n", s, s)
// %T 打印变量的类型
// %q 打印一个空字符串
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/04-string/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var s string
fmt.Printf("s (%T): %q\n", s, s)
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/05-undeclarables/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 不可声明的变量
//
// 1. 声明以下的变量
// 3speed
// !speed
// spe?ed
// var
// func
// package
//
// 2. 观察报错信息
//
// NOTE
// 上面这些变量的类型不重要
// ---------------------------------------------------------
func main() {
// var ? int
// var ? int
// var ? int
// var ? int
// var ? int
// var ? int
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/05-undeclarables/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// var 3speed int
// var !speed int
// var spe?ed int
// var var int
// var func int
// var package int
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/06-with-bits/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: 用 bit 声明
//
// 1. 使用以下类型声明几个变量
// int
// int8
// int16
// int32
// int64
// float32
// float64
// complex64
// complex128
// bool
// string
// rune
// byte
//
// 2. 观察他们的输出
//
// 3. 完成后,请查看 solution
// 并阅读在那的注释
//
// 期望输出
// 0 0 0 0 0 0 0 (0+0i) (0+0i) false 0 0
// ""
// ---------------------------------------------------------
func main() {
// var i int
// var i8 int8
// 从这里开始继续....
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/06-with-bits/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// 整数类型
var i int
var i8 int8
var i16 int16
var i32 int32
var i64 int64
// 浮点类型
var f32 float32
var f64 float64
// 复杂类型
var c64 complex64
var c128 complex128
// 布尔型
var b bool
// 字符串类型
var s string
var r rune // 同样是数字类型
var by byte // 同样是数字类型
fmt.Println(
i, i8, i16, i32, i64,
f32, f64,
c64, c128,
b, r, by,
)
// 你也可以使用 Println 做到
fmt.Printf("%q\n", s)
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/07-multiple/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 多重声明
//
// 1. 使用多重变量声明语句声明两个变量
//
// 2. 第一个变量的名称应该叫 active
// 3. 第二个变量的名称应该叫 delta
//
// 4. 把它们全打印出来
//
// HINT
// 你应该声明一个 bool 类型和一个 int 类型的变量
//
// 期望输出
// false 0
// ---------------------------------------------------------
func main() {
// var (
// ?
// )
// fmt.Println(active, delta)
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/07-multiple/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
active bool
delta int
)
fmt.Println(active, delta)
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/08-multiple-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 多重声明 #2
//
// 1. 使用多重变量声明语句声明并初始化两个字符串变量
//
// 2. 在声明变量的时候使用一次类型
//
// 3. 第一个变量的名称应该叫 firstName
// 4. 第二个变量的名称应该叫 lastName
//
// 5. 把它们全打印出来
//
// 期望输出
// "" ""
// ---------------------------------------------------------
func main() {
// 你的声明写在这里
//
// 使用你的变量的名称替换下面的问号
// fmt.Printf("%q %q\n", ?, ?)
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/08-multiple-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var firstName, lastName string = "", ""
fmt.Printf("%q %q\n", firstName, lastName)
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/09-unused/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 未使用的
//
// 1. 声明一个变量
//
// 2. 变量的名称应该叫: isLiquid
//
// 3. 使用空白标识符丢弃它
//
// NOTE
// 不要打印这个变量
// ---------------------------------------------------------
func main() {
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/09-unused/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
var isLiquid bool
_ = isLiquid
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/10-package-variable/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 包变量
//
// 1. 在包作用域内声明一个变量
//
// 2. 观察当你不使用它时是否会发生一些事情
// ---------------------------------------------------------
func main() {
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/10-package-variable/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
var isLiquid bool
func main() {
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/11-wrong-doer/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EXERCISE: 做错事的人
//
// 1. 打印一个变量
//
// 2. 然后声明它
// (意思是: 试着在它的声明前打印它)
//
// 3. 观察报错
// ---------------------------------------------------------
func main() {
// 先打印它:
// fmt.Println(?)
// 然后声明它:
// var ? ?
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/11-wrong-doer/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
func main() {
// 去掉下面代码的注释来查看报错
// fmt.Println(age)
// var age int
}
================================================
FILE: translation/chinese/06-变量/02-声明/练习/README.md
================================================
# 声明并打印变量
热身。声明几个变量,获得一些经验。熟悉变量声明的语法。
1. **[声明 int](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/01-int)**
2. **[声明 bool](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/02-bool)**
3. **[声明 float64](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/03-float64)**
4. **[声明 string](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/04-string)**
5. **[声明 不可声明的变量](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/05-undeclarables)**
6. **[使用 bits 声明变量](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/translation/chinese/06-with-bits)**
7. **[多重声明](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/07-multiple)**
8. **[多重声明 2](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/08-multiple-2)**
9. **[声明一个未使用的变量](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/09-unused)**
10. **[声明一个包变量](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/10-package-variable)**
11. **[在声明前使用](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/02-声明/练习/11-wrong-doer)**
================================================
FILE: translation/chinese/06-变量/02-声明/问题/01-what/README.md
================================================
# 问题: 什么是变量?
## 变量“住”在哪里?
* 硬盘
* 内存 - *正确*
* CPU
## 你使用变量名来做什么?
* 为了以后能够访问它 - *正确*
* 这只是一个标签
* 我不需要使用它。
## 如何改变一个变量的值?
* 通过变量名 - *正确*
* 通过变量值
* 通过向 Go 要求
## 在变量声明之后,你可以改变变量的类型吗??
* 可以 : Go 是动态类型
* 不行 : Go 是静态类型 - *正确*
* 两者都有: Go 支持两者
================================================
FILE: translation/chinese/06-变量/02-声明/问题/02-declaration/README.md
================================================
## 你需要使用哪条语句来声明变量?
* name int
* vars string name
* var name integer
* var width int *正确*
## 下面哪句话是正确的?
* 你可以在声明一个变量之前使用它
* 在使用一个变量之前,你必须先声明它 *正确*
## Go 是什么类型的语言?
* 弱类型
* 动态类型
* 强类型 *正确*
* 自由类型
## 下面哪个变量名是正确的?
* int
* four *正确*
* 2computers
* one?there
================================================
FILE: translation/chinese/06-变量/02-声明/问题/03-unused-variables/README.md
================================================
## 当你不使用一个块作用域中声明的变量会发生什么?
* 什么都不会发生, 它会正常工作
* 它将被自动删除
* 程序无法编译 *正确*
## 当你不使用一个包作用域中声明的变量会发生什么?
* 什么都不会发生, 它会正常工作 *正确*
* 它将被自动删除
* 程序无法编译
## 如何防止未使用变量的错误?
* 你可以改变变量的名称
* 你可以使用空白标识符来避免它 *正确*
* 你可以改变变量的类型
================================================
FILE: translation/chinese/06-变量/02-声明/问题/04-zero-values/README.md
================================================
## 哪种变量类型的零值是 0?
- bool
- pointer
- string
- 所有的数字类型 *正确*
## 哪种变量类型的零值是 false?
- bool *正确*
- pointer
- string
- 所有的数字类型
## 哪种变量类型的零值是 ""?
- bool
- pointer
- string *正确*
- 所有的数字类型
## 哪种变量类型的零值是 nil?
- bool
- pointer *正确*
- string
- 所有的数字类型
================================================
FILE: translation/chinese/06-变量/03-简短声明/01-初始化以及简短声明/01-初始化/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// = 是赋值操作符
// 当在一个变量声明中使用时,它将该变量初始化为给定的值
// 在这, Go 将 safe 变量初始化为 true
// 方案 #1(方案 #2 更好)
// var safe bool = true
// 方案 #2
var safe = true
fmt.Println(safe)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/01-初始化以及简短声明/02-简短声明/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// 方案 #1(方案 #2 更好)
// var safe bool = true
// 方案 #2 (还行)
// var safe = true
// 方案 #3 - 简短声明 (最佳)
//
// 你甚至不需要输入 var 关键词
//
// 简短声明等同于:
// var safe bool = true
// var safe = true
//
// Go从初始值中获取(推断)类型
//
// true 的默认类型是 bool
// 所以,变量 safe 的类型变成了 bool
safe := true
fmt.Println(safe)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/01-初始化以及简短声明/03-编码示例/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// var name string = "Carl"
// var name = "Carl"
name := "Carl"
// var isScientist bool = true
// var isScientist = true
isScientist := true
// var age int = 62
// var age = 62
age := 62
// var degree float64 = 5.
// var degree = 5.
degree := 5.
fmt.Println(name, isScientist, age, degree)
// 类型推断也适用于变量
//
// Go 获取变量的类型并将其分配给新声明的变量
//
// 现在name2变量的类型也是 `string`
name2 := name
fmt.Println(name2)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/02-包作用域/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// 你不能使用没有关键字的声明语句
// 简短声明没有关键字 (`var`)
// 所以, 它不能在包作用域上使用
//
// 语法错误:
// "函数体外的非声明语句"
// 原文:
// SYNTAX ERROR:
// "non-declaration statement outside function body"
// safe := true
// 然而, 你可以在包作用域上正常声明一个变量, 因为它有关键词: `var`
var safe = true
func main() {
fmt.Println(safe)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/03-多重简短声明/01-声明/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// the number of variables and values should be equal
// -> `true` is being assigned to `safe`
// -> `50` is being assigned to `speed`
safe, speed := true, 50
fmt.Println(safe, speed)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/03-多重简短声明/02-编码示例/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
name, lastname := "Nikola", "Tesla"
fmt.Println(name, lastname)
birth, death := 1856, 1943
fmt.Println(birth, death)
on, off := true, false
fmt.Println(on, off)
// 这里没有限制
// 然而, 随着你声明变量数量的增多, 代码的可读性会越来越差
degree, ratio, heat := 10.55, 30.5, 20.
fmt.Println(degree, ratio, heat)
// 你可以简短声明不同的变量类型
nFiles, valid, msg := 10, true, "hello"
fmt.Println(nFiles, valid, msg)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/03-多重简短声明/03-重声明/01/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// `safe` 的值是 `false`
var safe bool
// `safe` 的值现在是 `true`
// `speed` 被声明并初始化成了 `50`
// 只在以下情况下能进行重声明
//
// 至少一个重声明的变量是新变量
safe, speed := true, 50
fmt.Println(safe, speed)
// 练习
//
// 在"再次"简短声明前声明变量 speed ( 即在重声明语句前声明 speed 变量 )
//
// Observe what happens
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/03-多重简短声明/03-重声明/02-编码示例/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// 例 #1
name := "Nikola"
fmt.Println(name)
// name 已经在代码块里存在了
// name := "Marie"
// 给 name 赋了一个新值
// 并且声明一个新变量 age 并赋值 66
name, age := "Marie", 66
fmt.Println(name, age)
// 例 #2
// name = "Albert"
// birth := 1879
// 下面的重声明等同于上面的语句.
//
// `name` 是一个已经存在的变量
// Go 给变量 name 赋值了 "Albert"
//
// `birth` 是一个新变量
// Go 声明并给它赋值了 `1879`
name, birth := "Albert", 1879
fmt.Println(name, birth)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/04-简短-vs-正常/01-声明/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// 正常声明的使用例
// -----------------------------------------------------
// 当你需要一个包作用域变量时
// -----------------------------------------------------
// version := 0 // 不能这样
var version int
func main() {
// -----------------------------------------------------
// 如果你不知道初始值时
// -----------------------------------------------------
// 别这样做:
// score := 0
// 这样做:
// var score int
// -----------------------------------------------------
// 对变量进行分组以提高可读性
// -----------------------------------------------------
// var (
// video string
// duration int
// current int
// )
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/04-简短-vs-正常/02-简短声明/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// 简短声明的使用例
func main() {
// -----------------------------------------------------
// 如果你知道初始值
// -----------------------------------------------------
// 别这样做:
// var width, height = 100, 50
// 这样做 (简洁):
// width, height := 100, 50
// -----------------------------------------------------
// 重声明
// -----------------------------------------------------
// 别这样做:
// width = 50
// color := red
// 这样做 (简洁):
// width, color := 50, "red"
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/01-short-declare/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 简短声明
//
// 声明并打印四个变量,使用简短声明语句
//
// 期望输出
// i: 314 f: 3.14 s: Hello b: true
// ---------------------------------------------------------
func main() {
// 在这里写下你的声明语句
//
// 然后去掉下面代码的注释
// fmt.Println(
// "i:", i,
// "f:", f,
// "s:", s,
// "b:", b,
// )
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/01-short-declare/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
i := 314
f := 3.14
s := "Hello"
b := true
fmt.Println(
"i:", i,
"f:", f,
"s:", s,
"b:", b,
)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/02-multiple-short-declare/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 多重简短声明
//
// 使用多重简短声明语句声明两个变量
//
// 期望输出
// 14 true
// ---------------------------------------------------------
func main() {
// 在这里写下你的声明语句
//
// 然后去掉下面代码的注释
// fmt.Println(a, b)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/02-multiple-short-declare/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
a, b := 14, true
fmt.Println(a, b)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/03-multiple-short-declare-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 多重简短声明 #2
//
// 1. 使用多重简短声明语句声明两个变量
//
// 2. 变量 `a` 的值应该是 42
// 3. 变量 `c` 的值应该是 "good"
//
// 期望输出
// 42 good
// ---------------------------------------------------------
func main() {
// 在这里写下你的声明语句
//
// 然后去掉下面代码的注释
// fmt.Println(a, c)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/03-multiple-short-declare-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
a, c := 42, "good"
fmt.Println(a, c)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/04-short-with-expression/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 简短表达式
//
// 1. 间断声明一个变量 `sum`
//
// 2. 用一个 27 和 3.5 相加的语句初始化它的值
//
// 期望输出
// 30.5
// ---------------------------------------------------------
func main() {
// 在这里写下你的声明语句
//
// 然后去掉下面代码的注释
// fmt.Println(sum)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/04-short-with-expression/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
sum := 27 + 3.5
fmt.Println(sum)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/05-short-discard/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 简短丢弃
//
// 1. 简短声明两个 bool 变量
// (使用多重简短声明语法)
//
// 2. 初始化两个变量为 true
//
// 3. 改变你的声明并使用空白标识符
// 丢弃第二个变量的值
//
// 4. 仅打印第一个变量
//
// 期望输出
// true
// ---------------------------------------------------------
func main() {
// 在这里写下你的声明语句
//
// 然后去掉下面代码的注释
// fmt.Println(on)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/05-short-discard/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
// 你可以在简短的声明中舍弃数值
on, _ := true, true
fmt.Println(on)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/06-redeclare/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 重声明
//
// 1. 短声明两个 int 变量:age 和 yourAge
// (使用多重简短声明语法)
//
// 2. 声明一个新的 float 类型变量 ratio
// 修改变量 'age' 的值为 42
//
// (! 你应该用重声明)
//
// 4. 打印所有变量
//
// 期望输出
// 42, 20, 3.14
// ---------------------------------------------------------
func main() {
// 在这里写下你的声明语句
//
// 然后去掉下面代码的注释
// fmt.Println(age, yourAge, ratio)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/06-redeclare/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
age, yourAge := 10, 20
age, ratio := 42, 3.14
fmt.Println(age, yourAge, ratio)
}
================================================
FILE: translation/chinese/06-变量/03-简短声明/练习/README.md
================================================
# 简短声明
是时候使用简短的声明语法来声明一些变量了。除此之外还有重声明变量以及丢弃变量。
1. **[简短声明](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/03-简短声明/练习/01-short-declare)**
2. **[多重简短声明](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/03-简短声明/练习/02-multiple-short-declare)**
3. **[多重简短声明 #2](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/03-简短声明/练习/03-multiple-short-declare-2)**
4. **[简短表达式](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/03-简短声明/练习/04-short-with-expression)**
5. **[简短丢弃](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/03-简短声明/练习/05-short-discard)**
6. **[重声明](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/03-简短声明/练习/06-redeclare)**
================================================
FILE: translation/chinese/06-变量/03-简短声明/问题/README.md
================================================
## 哪个是正确的声明?
* var int safe := 3
* var safe bool := 3
* safe := true *正确*
## 哪个是正确的声明?
* var short := true
* int num := 1
* speed := 50 *正确*
* num int := 2
## 哪个是正确的声明?
* x, y, z := 10, 20
* x = 10,
* y, x, p := 5, "hi", 1.5 *正确*
* y, x = "hello", 10
## 哪个声明和下面的声明等价?
```go
var s string = "hi"
```
* var s int = "hi"
* s := "hi" *正确*
* s, p := 2, 3
## 哪个声明和下面的声明等价?
```go
var n = 10
```
* n := 10.0
* m, n := 1, 0
* var n int = 10 *正确*
## 变量 `s` 的类型是什么?
```go
s := "hmm..."
```
* bool
* string *正确*
* int
* float64
## 变量 `b` 的类型是什么?
```go
b := true
```
* bool *正确*
* string
* int
* float64
## 变量 `i` 的类型是什么?
```go
i := 42
```
* bool
* string
* int *正确*
* float64
## 变量 `f` 的类型是什么?
```go
f := 6.28
```
* bool
* string
* int
* float64 *正确*
## 变量 `x` 的类型是什么?
```go
y, x := false, 20
```
* 10
* 20 *正确*
* false
## 变量 `x` 的类型是什么?
```go
y, x := false, 20
x, z := 10, "hi"
```
* 10 *正确*
* 20
* false
## 下面哪个声明能在包作用域上使用?
* x := 10
* y, x := 10, 5
* var x, y = 5, 10 *正确*
================================================
FILE: translation/chinese/06-变量/04-赋值/01-概述/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var counter int
fmt.Println("counter's name : counter")
fmt.Println("counter's value:", counter)
fmt.Printf("counter's type : %T\n", counter)
counter = 10 // OK
// counter = "ten" // NOT OK
fmt.Println("counter's value:", counter)
counter++
fmt.Println("counter's value:", counter)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/01-赋值/01-赋值/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var speed int
fmt.Println(speed)
speed = 100
fmt.Println(speed)
speed = speed - 25
fmt.Println(speed)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/01-赋值/02-强类型/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Go 是一个强类型的编程语言
// 即使是 浮点 (float) 和 整数 (int) 也是不同的类型
// 甚至: int32 和 int 也是不同的类型
// 练习: 尝试去掉注释并观察错误
func main() {
var speed int
// speed = "100"
var running bool
// running = 1
var force float64
// speed = force
// Go 自动将无标注的 int 转换为 float64
force = 1
// 让编译器开心
_, _, _ = speed, running, force
}
================================================
FILE: translation/chinese/06-变量/04-赋值/01-赋值/03-例子/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
name string
age int
famous bool
)
// Example #1
name = "Newton"
age = 84
famous = true
fmt.Println(name, age, famous)
// Example #2
name = "Somebody"
age = 20
famous = false
fmt.Println(name, age, famous)
// Example #3
// EXERCISE: Why this doesn't work? Think about it.
// name = 20
// name = age
// save the previous value of the variable
// to a new variable
var prevName string
prevName = name
// overwrite the value of the original variable
// by assigning to it
name = "Einstein"
fmt.Println("previous name:", prevName)
fmt.Println("current name :", name)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/05-多重赋值/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
func main() {
var (
speed int
now time.Time
)
speed, now = 100, time.Now()
fmt.Println(speed, now)
// 练习:
// 尝试用这个替代式 (格式化时间).
// fmt.Println(speed, now.Format(time.Kitchen))
}
================================================
FILE: translation/chinese/06-变量/04-赋值/06-交换/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
speed = 100
prevSpeed = 50
)
speed, prevSpeed = prevSpeed, speed
fmt.Println(speed, prevSpeed)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/07-路径/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"path"
)
func main() {
var dir, file string
dir, file = path.Split("css/main.css")
fmt.Println("dir :", dir)
fmt.Println("file:", file)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/08-路径丢弃/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"path"
)
func main() {
var file string
_, file = path.Split("css/main.css")
fmt.Println("file:", file)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/09-路径简短声明/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"path"
)
func main() {
_, file := path.Split("css/main.css")
// 或者这样:
// dir, file := path.Split("css/main.css")
fmt.Println("file:", file)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/01-make-it-blue/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 让它变蓝
//
// 1. 修改 `color` 变量的值为 "blue"
//
// 2. 打印它
//
// 期望输出
// blue
// ---------------------------------------------------------
func main() {
// 去掉下面代码的注释:
// color := "green"
// 在下面写上你的代码:
// ?
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/01-make-it-blue/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
color := "green"
color = "blue"
fmt.Println(color)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/02-vars-to-vars/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 变量到变量
//
// 1. 修改 `color` 变量的值为 "dark green"
//
// 2. 不要直接将 "dark green" 赋值给 `color`
//
// 相反的, 在赋值时再次使用 `color` 变量 (即在赋值表达式中再次用到 `color`)
//
// 3. 打印它
//
// 限制
// 错误的答案, 别像这样做:
// `color = "dark green"`
//
// 提示
// + 操作符可以串联字符串的值
//
// 例子:
//
// "h" + "e" + "y" 返回 "hey"
//
// 期望输出
// dark green
// ---------------------------------------------------------
func main() {
// 去掉下面代码的注释:
// color := "green"
// 在下面写上你的代码:
// ?
// 去掉下面代码的注释以打印变量
// fmt.Println(color)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/02-vars-to-vars/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
color := "green"
// `"dark " + color` 是一个表达式
color = "dark " + color
fmt.Println(color)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/03-assign-with-expressions/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// 练习: 用表达式赋值
//
// 1. 用 3.14 乘 2 并赋值到变量 `n`
//
// 2. 打印 `n`
//
// 提示
// 例子: 3 * 2 = 6
// * 是乘法操作符 (它使数字相乘)
//
// 期望输出
// 6.28
// ---------------------------------------------------------
func main() {
// 别修改这里
// 声明一个新的 float64 变量
// 0. 代表 0.0
n := 0.
// 在下面写上你的代码:
// ?
fmt.Println(n)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/03-assign-with-expressions/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
n := 0.
n = 3.14 * 2
fmt.Println(n)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/04-find-the-rectangle-perimeter/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 找到矩形的周长
//
// 1. 找到矩形的周长
// 宽为 5
// 高为 6
//
// 2. 把结果复制到 `perimeter` 变量上
//
// 3. 打印 `perimeter`
//
// 提示
// 公式 = 2 × (宽 + 高)
//
// 期望输出
// 22
//
// 附加题
// 在这里找到更多的公式,并在新的程序中计算它们
// https://www.mathsisfun.com/area.html
// ---------------------------------------------------------
func main() {
// 去掉下面代码的注释
// var (
// perimeter int
// width, height = 5, 6
// )
// 计算结果时使用上述变量
// 在下面写上你的代码:
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/04-find-the-rectangle-perimeter/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
perimeter int
width, height = 5, 6
)
// 首先计算: (宽 + 高)
// 然后 : 用 2 与它相乘
// 就和在数学里一样
perimeter = 2 * (width + height)
fmt.Println(perimeter)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/05-multi-assign/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// 练习: 多重赋值
//
// 1. 使用多重赋值语句把 "go" 赋值到变量 `lang` 上
// 以及 2 到变量 `version` 上
// 2. 打印这些变量
//
// 期望输出
// go version 2
// ---------------------------------------------------------
func main() {
// 别动这些
var (
lang string
version int
)
// 在下面写上你的代码:
// 别碰这个
fmt.Println(lang, "version", version)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/05-multi-assign/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
lang string
version int
)
lang, version = "go", 2
fmt.Println(lang, "version", version)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/06-multi-assign-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 多重赋值 #2
//
// 1. 将正确的值赋给各变量以和下面的 期望输出 相匹配
//
// 2. 打印这些变量
//
// 提示
// 使用多个 Println 调用来打印每个句子
//
// 期望输出
// Air is good on Mars
// It's true
// It is 19.5 degrees
// ---------------------------------------------------------
func main() {
// 去掉下面代码的注释
// var (
// planet string
// isTrue bool
// temp float64
// )
// 在下面写上你的代码
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/06-multi-assign-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
planet string
isTrue bool
temp float64
)
planet, isTrue, temp = "Mars", true, 19.5
fmt.Println("Air is good on", planet)
fmt.Println("It's", isTrue)
fmt.Println("It is", temp, "degrees")
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/07-multi-short-func/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 多重简短函数
//
// 1. 使用多重简短声明语法声明两个变量
//
// 2. 使用下方的 `multi` 函数初始化变量
//
// 3. 在声明中丢弃第一个变量
//
// 4. 只打印第二个变量
//
// 注意
// 你应该在初始化时使用 `multi` 函数
//
// 期望输出
// 4
// ---------------------------------------------------------
func main() {
// 在这添加你的声明
//
// 然后删掉下面代码的注释
// fmt.Println(b)
}
// multi 是一个返回多个 int 值的函数
func multi() (int, int) {
return 5, 4
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/07-multi-short-func/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
)
func main() {
_, b := multi()
fmt.Println(b)
}
func multi() (int, int) {
return 5, 4
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/08-swapper/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 交换器
//
// 1. 同时将`color`改为 "orange", `color2` 改为 "绿色"。
// (使用多重赋值)
//
// 2. 打印这些变量
//
// 期望输出
// orange green
// ---------------------------------------------------------
func main() {
// 去掉下面代码的注释
// color, color2 := "red", "blue"
// ?
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/08-swapper/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
color, color2 := "red", "blue"
color, color2 = "orange", "green"
fmt.Println(color, color2)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/09-swapper-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 交换器 #2
//
// 1. 交换 `red` 和 `blue` 这两个变量的值
//
// 2. 打印它们
//
// 期望输出
// blue red
// ---------------------------------------------------------
func main() {
// 去掉下面代码的注释:
// red, blue := "red", "blue"
// ?
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/09-swapper-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
red, blue := "red", "blue"
red, blue = blue, red
fmt.Println(red, blue)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/10-discard-the-file/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 丢弃文件
//
// 1. 使用 `path.Split`, 只打印 directory
//
// 2. 丢弃它 file 的部分
//
// 限制
// 使用简短声明
//
// 期望输出
// secret/
// ---------------------------------------------------------
func main() {
// 去掉下面代码的注释:
// ? ?= path.Split("secret/file.txt")
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/10-discard-the-file/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"path"
)
func main() {
dir, _ := path.Split("secret/file.txt")
fmt.Println(dir)
}
================================================
FILE: translation/chinese/06-变量/04-赋值/练习/README.md
================================================
# 赋值
赋值意味着 "复制" 值。在 Go 中, 所有东西都被复制了。之后你会了解更多这方面的信息。
现在, 脚踏实地尝试一些赋值练习
1. **[让他变蓝](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/04-赋值/练习/01-make-it-blue)**
2. **[变量到变量](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/04-赋值/练习/02-vars-to-vars)**
3. **[用表达式赋值](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/04-赋值/练习/03-assign-with-expressions)**
4. **[找到矩形的周长](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/04-赋值/练习/04-find-the-rectangle-perimeter)**
5. **[多重赋值](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/04-赋值/练习/05-multi-assign)**
6. **[多重赋值 #2](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/04-赋值/练习/06-multi-assign-2)**
7. **[多重简短函数](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/04-赋值/练习/07-multi-short-func)**
8. **[交换器](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/04-赋值/练习/08-swapper)**
9. **[交换器 #2](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/04-赋值/练习/09-swapper-2)**
10. **[丢弃文件](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/04-赋值/练习/10-discard-the-file)**
================================================
FILE: translation/chinese/06-变量/04-赋值/问题/README.md
================================================
## 当你把一个变量赋值给另一个变量时会发生什么?
* 变量们变成同一个
* 被赋值的变量被删除
* 变量的值被改变为赋值变量的值 *正确*
## 哪个是正确的赋值语句?
```go
opened := true
```
* `closed := true`
* `opened = false` *正确*
* `var x = 2`
## 哪个是正确的赋值语句?
* `a, b = 3; 5`
* `c, d = true, false` *正确*
* `a, b, c = 5, 3`
## 哪个是正确的赋值语句?
```go
var (
n = 3
m int
)
```
* `m = "4"`
* `n = 10` *正确*
* `n = true`
* `m = false`
## 哪个是正确的赋值语句?
```go
var (
n = 3
m int
f float64
)
// one of the assignments below will be here
fmt.Println(n, m, f)
```
* `n, m = 4, f`
* `n = false`
* `n, m, f = m + n, n + 5, 0.5` *正确*
* `n, m = 3.82, "hi"`
## 哪个是正确的赋值语句?
```go
var (
a int
c bool
)
```
* `a = _`
* `c, _ = _, false`
* `_, _ = a, c` *正确*
## 哪个是正确的赋值语句?
**记住:** `path.Split` 返回两个 `string` 值
```go
var c, f string
```
* `_ = path.Split("assets/profile.png")`
* `_, _, c = path.Split("assets/profile.png")`
* `f = path.Split("assets/profile.png")`
* `_, f = path.Split("assets/profile.png")` *正确*
================================================
FILE: translation/chinese/06-变量/05-类型转换/01-破坏性的/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
speed := 100 // int
force := 2.5 // float64
// 错误: 无效的操作符
// ERROR: invalid op
// speed = speed * force
// 转换可以是一个破坏性的操作
// `force` 失去了它的分数部分...
speed = speed * int(force)
fmt.Println(speed)
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/02-正确的/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// 转化的顺序很重要...
func main() {
speed := 100
force := 2.5
fmt.Printf("speed : %T\n", speed)
fmt.Printf("conversion: %T\n", float64(speed))
fmt.Printf("expression: %T\n", float64(speed)*force)
// 类型不匹配:
// speed 是 int
// expression 是 float64
// speed = float64(speed) * force
// 正确: int * int
speed = int(float64(speed) * force)
fmt.Println(speed)
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/03-数型转换/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var apple int
var orange int32
// 错误:
// 不能将 orange 赋值到 apple 上 (不同的类型)
// ERROR:
// cannot assign orange to apple (different types)
// apple = orange
// 你需要将 orange 转换为 apple
// orange 能够被转换为 int ,
// 因为 int 和 int32 都是数字类型
apple = int(orange)
// 你不能将一个数字类型转换为布尔类型
// isDelicious := bool(orange)
// 但是你可以将 int 转换为 string
// 这只对 int 类型生效
orange = 65 // 65 is A
color := string(orange)
fmt.Println(color)
// 这不能运行。 65.0 是 float.
// fmt.Println(string(65.0))
// 这能运行: 这有两个 byte 值
// byte 也是 int
fmt.Println(string([]byte{104, 105}))
_ = apple
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/01-convert-and-fix/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 转换并修复
//
// 使用类型转换表达式修复这些代码.
//
// 期望输出
// 15.5
// ---------------------------------------------------------
func main() {
// a, b := 10, 5.5
// fmt.Println(a + b)
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/01-convert-and-fix/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
a, b := 10, 5.5
fmt.Println(float64(a) + b)
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/02-convert-and-fix-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 转换并修复 #2
//
// 使用类型转换表达式修复这些代码.
//
// 期望输出
// 10.5
// ---------------------------------------------------------
func main() {
// a, b := 10, 5.5
// a = b
// fmt.Println(a + b)
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/02-convert-and-fix-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
a, b := 10, 5.5
a = int(b)
fmt.Println(float64(a) + b)
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/03-convert-and-fix-3/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 转换并修复 #3
//
// 修复代码.
//
// 期望输出
// 5.5
// ---------------------------------------------------------
func main() {
// fmt.Println(int(5.5))
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/03-convert-and-fix-3/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println(5.5)
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/04-convert-and-fix-4/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 转换并修复 #4
//
// 修复代码.
//
// 期望输出
// 9.5
// ---------------------------------------------------------
func main() {
// age := 2
// fmt.Println(int(7.5) + int(age))
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/04-convert-and-fix-4/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
age := 2
fmt.Println(7.5 + float64(age))
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/05-convert-and-fix-5/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// ---------------------------------------------------------
// 练习: 转换并修复 #5
//
// 修复代码.
//
// 提示
// int8 的最大值是 127
// int16 的最大值是 32767
//
// 期望输出
// 1127
// ---------------------------------------------------------
func main() {
// 不要修改这些变量
min := int8(127)
max := int16(1000)
// 修复代码
fmt.Println(int8(max) + min)
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/05-convert-and-fix-5/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
min := int8(127)
max := int16(1000)
fmt.Println(max + int16(min))
// 解释
//
// `int8(max)` 损失了 max 的信息
// 导致它减小到了 127
// 也就是 int8 的最大值
//
// 正确的转换时 int16(min)
// 因为 int16 > int8
// 当你这样做时, min 不会损失信息
//
// 你会在 "Go 类型系统" 这节学到更多
}
================================================
FILE: translation/chinese/06-变量/05-类型转换/练习/README.md
================================================
# 类型转换
这里为你准备了 5 个练习。你必须找到这些错误,然后用正确的类型转换来修复它们。
1. **[Convert and Fix #1](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/05-类型转换/练习/01-convert-and-fix)**
2. **[Convert and Fix #2](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/05-类型转换/练习/02-convert-and-fix-2)**
3. **[Convert and Fix #3](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/05-类型转换/练习/03-convert-and-fix-3)**
4. **[Convert and Fix #4](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/05-类型转换/练习/04-convert-and-fix-4)**
5. **[Convert and Fix #5](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/05-类型转换/练习/05-convert-and-fix-5)**
================================================
FILE: translation/chinese/06-变量/05-类型转换/问题/questions.md
================================================
## 哪一个是正确的类型转换表达式?
* convert(40)
* var("hi")
* int(4.) *正确*
* int[4]
## 这段代码打印什么?
```go
age := 6.5
fmt.Print(int(age))
```
* 6.5
* 65
* 6 *正确*
* .5
> 当你把一个 float 转换为 int 时
> 它失去了它的小数部分
## 这段代码打印什么?
```go
fmt.Print(int(6.5))
```
* 6.5
* 65
* 6
* Compile-Time Error *正确*
> Go可以在编译时检测转换错误
## 这段代码打印什么?
```go
area := 10.5
fmt.Print(area/2)
```
* 5.25 *正确*
* 5
* 0
* Error
## 这段代码打印什么?
```go
area := 10.5
div := 2
fmt.Print(area/div)
```
* 5.25
* 5
* ERROR *正确*
> 你不能除以不同类型的值
> 你需要转换:`area / float64(div)`
## 下面哪段代码能修复这段代码?
```go
area := 10.5
div := 2
fmt.Print(area/div)
```
* `fmt.Print(int(area)/div)` // 5
* `fmt.Print(area/int(div))` // 类型不匹配
* `fmt.Print(int(area)/int(div))` // 5
* `fmt.Print(area/float64(div))` *正确*
================================================
FILE: translation/chinese/06-变量/06-问候员项目/01-演示/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// 注意: 至少要用3个参数来运行这个程序
// 否则它会报错
func main() {
fmt.Printf("%#v\n", os.Args)
// 从 os.Args 字符串切片中获取一个 item
// os.Args[INDEX]
// INDEX 可以是 0 或者更大
fmt.Println("Path:", os.Args[0])
fmt.Println("1st argument:", os.Args[1])
fmt.Println("2nd argument:", os.Args[2])
fmt.Println("3rd argument:", os.Args[3])
// `len` 可以知道有多少个 item 在切片值中
fmt.Println("Items inside os.Args:", len(os.Args))
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/02-版本1/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// 因为, 还没有学到关于控制流语句的知识
// 在这里没有包含错误检测
//
// 所以, 如果你没有传递 name,
// 程序会出错,
// 这是有意为之的
func main() {
var name string
// 给下面的字符串变量赋一个新值
name = os.Args[1]
fmt.Println("Hello great", name, "!")
// 修改 name, 声明 age 并赋值 85
name, age := "gandalf", 85
fmt.Println("My name is", name)
fmt.Println("My age is", age)
fmt.Println("BTW, you shall pass!")
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/03-版本2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// 因为, 还没有学到关于控制流语句的知识
// 在这里没有包含错误检测
//
// 所以, 如果你没有传递 name,
// 程序会出错,
// 这是有意为之的
func main() {
// 给下面的字符串变量赋一个新值
name := os.Args[1]
fmt.Println("Hello great", name, "!")
// 修改 name, 声明 age 并赋值 85
name, age := "gandalf", 85
fmt.Println("My name is", name)
fmt.Println("My age is", age)
fmt.Println("BTW, you shall pass!")
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/01-count-arguments/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 数参数
//
// 打印命令行参数的个数
//
// 输入
// bilbo balbo bungo
//
// 期望输出
// There are 3 names.
// ---------------------------------------------------------
func main() {
// 去掉注释 & 修复代码
// count := ?
// 去掉注释 & 然后别动他
// fmt.Printf("There are %d names.\n", count)
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/01-count-arguments/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
count := len(os.Args) - 1
fmt.Printf("There are %d names.\n", count)
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/02-print-the-path/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 打印路径
//
// 从变量 `os.Args` 中获取运行程序的路径并打印它
//
// 提示
// 用 `go build` 来构建你的程序
// 然后通过编译后的可执行程序运行它
//
// 预期输出应包含
// myprogram
// ---------------------------------------------------------
func main() {
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/02-print-the-path/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// 步骤:
//
// 输入下面的命令来编译:
// go build -o myprogram
//
// 然后输入下面的命令来运行:
// ./myprogram
//
// 如果是 Windows, 输入:
// myprogram
func main() {
fmt.Println(os.Args[0])
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/03-print-your-name/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 打印你的名字
//
// 从第一个命令行参数来获取名字
//
// 输入
// 用你的名字来运行这个程序 (指传入你的名字作为参数)
//
// 期望输出
// 你的名字
//
// 例子
// go run main.go inanc
//
// inanc
//
// 附加题: 让输出变成下面这样:
//
// go run main.go inanc
// Hi inanc
// How are you?
// ---------------------------------------------------------
func main() {
// 从第一个命令行参数来获取名字
// 打印它
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/03-print-your-name/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println(os.Args[1])
// 附加题答案
fmt.Println("Hello", os.Args[1])
fmt.Println("How are you?")
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/04-greet-more-people/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 问候更多人
//
// 限制
// 1. 请确保与下面的预期输出相匹配
// 2. 将参数的长度存储在一个变量中
// 3. 将所有参数也存储在变量中
//
// 输入
// bilbo balbo bungo
//
// 期望输出
// There are 3 people!
// Hello great bilbo !
// Hello great balbo !
// Hello great bungo !
// Nice to meet you all.
// ---------------------------------------------------------
func main() {
// 在这写你的代码
// 附加题 #1:
// 传递少于3个参数, 然后观察错误。
// 在网上搜索如何解决这个问题
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/04-greet-more-people/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
var (
l = len(os.Args) - 1
n1 = os.Args[1]
n2 = os.Args[2]
n3 = os.Args[3]
)
fmt.Println("There are", l, "people !")
fmt.Println("Hello great", n1, "!")
fmt.Println("Hello great", n2, "!")
fmt.Println("Hello great", n3, "!")
fmt.Println("Nice to meet you all.")
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/05-greet-5-people/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 问候 5 个人
//
// 这次问候 5 个人
//
// 不要从上一个练习中复制粘贴代码
//
// 限制
// 这次不要用变量
//
// 输入
// bilbo balbo bungo gandalf legolas
//
// 期望输出
// There are 5 people!
// Hello great bilbo !
// Hello great balbo !
// Hello great bungo !
// Hello great gandalf !
// Hello great legolas !
// Nice to meet you all.
// ---------------------------------------------------------
func main() {
// 在这写你的代码
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/05-greet-5-people/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("There are", len(os.Args)-1, "people !")
fmt.Println("Hello great", os.Args[1], "!")
fmt.Println("Hello great", os.Args[2], "!")
fmt.Println("Hello great", os.Args[3], "!")
fmt.Println("Hello great", os.Args[4], "!")
fmt.Println("Hello great", os.Args[5], "!")
fmt.Println("Nice to meet you all.")
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/README.md
================================================
# 命令行参数
1. **[数参数](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/06-问候员项目/练习/01-count-arguments)**
2. **[打印路径](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/06-问候员项目/练习/02-print-the-path)**
3. **[打印你的名字](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/06-问候员项目/练习/03-print-your-name)**
4. **[问候更多人](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/06-问候员项目/练习/04-greet-more-people)**
5. **[问候 5 个人](https://github.com/inancgumus/learngo/tree/master/translation/chinese/06-变量/06-问候员项目/练习/05-greet-5-people)**
================================================
FILE: translation/chinese/06-变量/06-问候员项目/练习/solution-to-the-lecture-exercise/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
// ---------------------------------------------------------
// 这是我在讲座中提到的练习的答案
// ---------------------------------------------------------
// 注意: 你至少要用 3 个参数来运行这个程序
// 否则它会报错
func main() {
// 给下面的字符串变量赋一个新值
var (
name = os.Args[1]
name2 = os.Args[2]
name3 = os.Args[3]
)
fmt.Println("Hello great", name, "!")
fmt.Println("And hellooo to you magnificient", name2, "!")
fmt.Println("Welcome", name3, "!")
// 修改 name, 声明 age 变量并赋值 131
name, age := "bilbo baggins", 131 // 未知年龄!
fmt.Println("My name is", name)
fmt.Println("My age is", age)
fmt.Println("And, I love adventures!")
}
================================================
FILE: translation/chinese/06-变量/06-问候员项目/问题/questions.md
================================================
## `os.Args` 变量在其第一项中存储了什么?
* 传递给程序的第一个参数
* 传递给程序的第二个参数
* 运行程序的路径 *正确*
## `Args` 变量的类型是什么?
```go
var Args []string
```
* string
* string 数组
* strings 的切片 *正确*
## `Args` 变量中每个值的类型是什么?
```go
var Args []string
```
* string *正确*
* string 数组
* strings 的切片
## 如何获得 `Args` 变量的第一项?
```go
var Args []string
```
* Args.0
* Args{1}
* Args[0] *正确*
* Args(1)
## 如何获得 `Args` 变量的第二项?
```go
var Args []string
```
* Args.2
* Args[1] *正确*
* Args{1}
* Args(2)
## 如何获得 `Args` 变量的长度?
```go
var Args []string
```
* length(Args)
* Args.len
* len(Args) *正确*
* Args.Length
## 如何从命令行获得第一个 "argument"?
* os.Args[0]
* os.Args[1] *正确*
* os.Args[2]
* os.Args[3]
================================================
FILE: translation/chinese/07-打印/01-介绍/01-println-vs-printf/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
ops, ok, fail := 2350, 543, 433
fmt.Println(
"total:", ops, "- success:", ok, "/", fail,
)
fmt.Printf(
"total: %d - success: %d / %d\n",
ops, ok, fail,
)
}
================================================
FILE: translation/chinese/07-打印/01-介绍/02/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var brand string
// 像这样 "" 引用形式打印字符串
fmt.Printf("%q\n", brand)
brand = "Google"
fmt.Printf("%q\n", brand)
}
================================================
FILE: translation/chinese/07-打印/02-转义序列/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// 没有换行符
fmt.Println("hihi")
// 使用换行符:
// \n = 转义序列
// \ = 转义字符
fmt.Println("hi\nhi")
// 转义字符:
// \\ = \
// \" = "
fmt.Println("hi\\n\"hi\"")
}
================================================
FILE: translation/chinese/07-打印/03-打印类型/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// 我正在使用一次声明多个变量,而不是一次声明一个变量
var (
speed int
heat float64
off bool
brand string
)
fmt.Printf("%T\n", speed)
fmt.Printf("%T\n", heat)
fmt.Printf("%T\n", off)
fmt.Printf("%T\n", brand)
}
================================================
FILE: translation/chinese/07-打印/04-编程/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
var (
planet = "venus"
distance = 261
orbital = 224.701
hasLife = false
)
// 全能打印 %v 动词
fmt.Printf("Planet: %v\n", planet)
fmt.Printf("Distance: %v millions kms\n", distance)
fmt.Printf("Orbital Period: %v days\n", orbital)
fmt.Printf("Does %v have life? %v\n", planet, hasLife)
// 参数索引 - 索引从 1 开始
fmt.Printf(
"%v is %v away. Think! %[2]v kms! %[1]v OMG.\n",
planet, distance,
)
// 为什么不使用别的打印词?
// 原因: 有可能因为类型不正确导致报错
//
// fmt.Printf("Planet: %d\n", planet)
// fmt.Printf("Distance: %s millions kms\n", distance)
// fmt.Printf("Orbital Period: %t days\n", orbital)
// fmt.Printf("Does %v has life? %f\n", planet, hasLife)
// 正确的打印动词:
// fmt.Printf("Planet: %s\n", planet)
// fmt.Printf("Distance: %d millions kms\n", distance)
// fmt.Printf("Orbital Period: %f days\n", orbital)
// fmt.Printf("Does %s has life? %t\n", planet, hasLife)
// 更加精确的打印动词
fmt.Printf("Orbital Period: %f days\n", orbital)
fmt.Printf("Orbital Period: %.0f days\n", orbital)
fmt.Printf("Orbital Period: %.1f days\n", orbital)
fmt.Printf("Orbital Period: %.2f days\n", orbital)
}
================================================
FILE: translation/chinese/07-打印/练习/01-print-your-age/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: 打印你的年来
//
// 使用 Printf 打印你的年龄
//
// 期望输出
// I'm 30 years old.
//
// 注意
// 你应该把你的年龄给程 30 岁
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: translation/chinese/07-打印/练习/01-print-your-age/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("I'm %d years old.\n", 30)
}
================================================
FILE: translation/chinese/07-打印/练习/02-print-your-name-and-lastname/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习:打印您的名字和姓氏
//
// 使用 Printf 您的名字和姓氏
//
// 期望输出
// My name is Inanc and my lastname is Gumus.
//
// 额外
// 把打印格式声明字符串 (Printf 的第一个参数) 存到一个变量
// 然后传递到 Printf
// ---------------------------------------------------------
func main() {
// 额外: 使用一个变量存打印格式声明字符串
// fmt.Printf("?", ?, ?)
}
================================================
FILE: translation/chinese/07-打印/练习/02-print-your-name-and-lastname/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("My name is %s and my lastname is %s.\n", "Inanc", "Gumus")
// 额外
msg := "My name is %s and my lastname is %s.\n"
fmt.Printf(msg, "Inanc", "Gumus")
}
================================================
FILE: translation/chinese/07-打印/练习/03-false-claims/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习: false 声明
//
// 使用 Printf 使用变量打印预期输出
//
// 期望输出
// These are false claims.
// ---------------------------------------------------------
func main() {
// 将注释下的代码去掉注释
// 然后移到你的代码中
// tf := false
// 将你的代码写到下面
// ?
}
================================================
FILE: translation/chinese/07-打印/练习/03-false-claims/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
tf := false
fmt.Printf("These are %t claims.\n", tf)
}
================================================
FILE: translation/chinese/07-打印/练习/04-print-the-temperature/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习:打印温度
//
// 使用 Printf 打印您所在地区的当前温度
//
// 注意
// 不要使用 %v 动词
// 输出不应该是 29.500000
//
// 期望输出
// Temperature is 29.5 degrees.
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: translation/chinese/07-打印/练习/04-print-the-temperature/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("Temperature is %.1f degrees.\n", 29.5)
}
================================================
FILE: translation/chinese/07-打印/练习/05-double-quotes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习:双引号
//
// 使用 Printf 打印带有双引号的 "hello world"
//(正如你在这里看到的)
//
// 注意
// 输出不应该只是 hello world
//
// 期待输出
// "hello world"
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: translation/chinese/07-打印/练习/05-double-quotes/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("%q\n", "hello world")
}
================================================
FILE: translation/chinese/07-打印/练习/06-print-the-type/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习:打印字体
//
// 使用 fmt.Printf 打印 3 的类型和值
//
// 期望输出
// Type of 3 is int
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: translation/chinese/07-打印/练习/06-print-the-type/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("Type of %d is %[1]T\n", 3)
}
================================================
FILE: translation/chinese/07-打印/练习/07-print-the-type-2/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习:打印类型#2
//
// 使用 fmt.Printf 打印 3.14 的类型和值
//
// 期望输出
// Type of 3.14 is float64
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: translation/chinese/07-打印/练习/07-print-the-type-2/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("Type of %.2f is %[1]T\n", 3.14)
}
================================================
FILE: translation/chinese/07-打印/练习/08-print-the-type-3/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习:打印类型#3
//
// 使用 fmt.Printf 打印 "hello" 的类型和值
//
// 期望输出
// Type of hello is string
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: translation/chinese/07-打印/练习/08-print-the-type-3/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("Type of %s is %[1]T\n", "hello")
}
================================================
FILE: translation/chinese/07-打印/练习/09-print-the-type-4/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习:打印类型#4
// 使用 fmt.Printf 打印 true 的类型和值
//
// 期望输出
// Type of true is bool
// ---------------------------------------------------------
func main() {
// ?
}
================================================
FILE: translation/chinese/07-打印/练习/09-print-the-type-4/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Printf("Type of %t is %[1]T\n", true)
}
================================================
FILE: translation/chinese/07-打印/练习/10-print-your-fullname/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// 练习:打印您的全名
//
// 1. 从命令行获取您的名字和姓氏
// 2. 使用 Printf 打印它们
//
// 输入示例
// Inanc Gumus
//
// 期望输出
// Your name is Inanc and your lastname is Gumus.
// ---------------------------------------------------------
func main() {
// 额外: 使用一个变量存打印格式
}
================================================
FILE: translation/chinese/07-打印/练习/10-print-your-fullname/solution/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
// 警告: 该程序如果允许时不输入你的名字和姓氏将会报错
name, lastname := os.Args[1], os.Args[2]
msg := "Your name is %s and your lastname is %s.\n"
fmt.Printf(msg, name, lastname)
}
================================================
FILE: translation/chinese/07-打印/练习/README.md
================================================
# 打印
1. **[Print Your Age](https://github.com/inancgumus/learngo/tree/master/translation/chinese/07-变量/练习/01-print-your-age)**
2. **[Print Your Name and LastName](https://github.com/inancgumus/learngo/tree/master/translation/chinese/07-变量/练习/02-print-your-name-and-lastname)**
3. **[False Claims](https://github.com/inancgumus/learngo/tree/master/translation/chinese/07-变量/练习/03-false-claims)**
4. **[Print the Temperature](https://github.com/inancgumus/learngo/tree/master/translation/chinese/07-变量/练习/04-print-the-temperature)**
5. **[Double Quotes](https://github.com/inancgumus/learngo/tree/master/translation/chinese/07-变量/练习/05-double-quotes)**
6. **[Print the Type](https://github.com/inancgumus/learngo/tree/master/translation/chinese/07-变量/练习/06-print-the-type)**
7. **[Print the Type #2](https://github.com/inancgumus/learngo/tree/master/translation/chinese/07-变量/练习/07-print-the-type-2)**
8. **[Print the Type #3](https://github.com/inancgumus/learngo/tree/master/translation/chinese/07-变量/练习/08-print-the-type-3)**
9. **[Print the Type #4](https://github.com/inancgumus/learngo/tree/master/translation/chinese/07-变量/练习/09-print-the-type-4)**
10. **[Print Your Fullname](https://github.com/inancgumus/learngo/tree/master/translation/chinese/07-变量/练习/10-print-your-fullname)**
================================================
FILE: translation/chinese/07-打印/问题/questions.md
================================================
## 哪个代码是正确的?
* `fmt.Printf("Hi %s")`
* `fmt.Printf("Hi %s", "how", "are you")`
* `fmt.Printf("Hi %s", "hello")` *正确*
* `fmt.Printf("Hi %s", true)`
## 哪个代码是正确的?
* `fmt.Printf("Hi %s %s", "there")`
* `fmt.Printf("Hi %s %s", "5", true)`
* `fmt.Printf("Hi %s %s", "there", ".")` *正确*
* `fmt.Printf("Hi %s %s", "true", false)`
## 哪个动词用于 int 值?
* %f
* %d *正确*
* %s
* %t
## 哪个动词用于 float 值?
* %f *正确*
* %d
* %s
* %t
## 哪个动词用于 string 值?
* %f
* %d
* %s *正确*
* %t
## 哪个动词用于 bool 值?
* %f
* %d
* %s
* %t *正确*
## 你可以用哪个动词来形容任何类型的值?
* %f
* %d
* %v *正确*
* %t
## 哪个是 `"\n"` 正确打印?
* \n
* Prints a newline *正确*
* Prints an empty string
## 哪个是 `"\\n"` 正确打印?
* \n *正确*
* Prints a newline
* Prints an empty string
## 哪个是 "c:\\secret\\directory" 正确打印?
* "c:\\secret\\directory"
* c:\\secret\\directory
* c:\secret\directory *正确*
## 哪个是 `"\"heisenberg\""` 正确打印?
* ERROR
* heisenberg
* "heisenberg" *正确*
* 'heisenberg'
## 哪个是 `fmt.Printf("%T", 3.14)` 正确输出?
* ERROR
* int
* float64 *正确*
* string
* bool
## 哪个是 `fmt.Printf("%T", true)` 正确输出?
* ERROR
* int
* float64
* string
* bool *正确*
## 哪个是 `fmt.Printf("%T", 42)` 正确输出?
* ERROR
* int *正确*
* float64
* string
* bool
## 哪个是 `fmt.Printf("%T", "hi")` 正确输出?
* ERROR
* int
* float64
* string *正确*
* bool
================================================
FILE: translation/spanish/01-empecemos/README.md
================================================
# Guias De Instalación Para Go
Por favor seleciona tu sistema operativo:
- [OS X](instalacion-osx.md)
- [Windows](instalacion-windows.md)
- [Linux (Ubuntu)](instalacion-ubuntu.md)
================================================
FILE: translation/spanish/01-empecemos/instalacion-osx.md
================================================
# Instalación OSX
## NOTA
Si tienes [homebrew](https://brew.sh) instalado, puedes instalar Go facilmente de la siguiente forma:
```bash
# si no tienes git instalado instálalo asi
brew install git
# despues instala go
brew install go
# añade la ruta GOBIN a tu ruta en ~/.bash_profile
export PATH=${HOME}/go/bin:$PATH
```
## 1. Instala el editor [Visual Studio Code](https://code.visualstudio.com)
1. Instálalo pero no lo abras todavia
2. Ve a [https://code.visualstudio.com](https://code.visualstudio.com)
3. Selecciona la version OS X (Mac) para comenzar la descarga
4. Descomprime los archivos descargados y muevelos a la carpeta `~/Applications`
## 2. Instala [Git](https://git-scm.com/)
1. Descarga y ejecuta el instalador. Ve a: [https://git-scm.com/downloads](https://git-scm.com/downloads)
2. Selecciona VSCode como editor por defecto
## 3. Instala [Go](https://golang.org/)
1. Ve a [https://golang.org/dl](https://golang.go/dl)
2. Elige la versión OS X (Mac)
3. Ejecuta el instalador
## 4. Configura Visual Studio Code
1. Abre VS Code; haz click en la pestaña de extensiones situada a la izquierda, busca "go" e instálalo
2. Cierra VS Code por completo y ábrelo de nuevo
3. Ve al menu 'Ver' y selecciona **Paleta de Comandos**
1. O simplemente presiona: `ctrl+shift+p`
2. Escribe: `go install`
3. Elige: _"Go: Install/Update Tools"_
4. Marca todas las casillas
4. Una vez acabado abre la **Paleta de Comandos** de nuevo
1. Escribe: `shell`
2. Elige: "Install 'code' command in PATH"
1. **NOTA:** No tienes que hacer esto si estas en Windows.
## Eso es todo! Disfrutad! 🤩
> Para mas tutoriales: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2021 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click aqui para leer la licencia.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/spanish/01-empecemos/instalacion-ubuntu.md
================================================
# Instalación Linux (Ubuntu)
Si quieres usar snap puedes instalar Go facilmente con este comando:
```bash
sudo snap install go --classic
```
Sino, puedes seguir los siguientes pasos
## 1. Actualiza los paquetes locales
```bash
sudo apt-get update
```
## 2. Instala [Git](https://git-scm.com/)
```bash
sudo apt-get install git
```
## 3. Instala [Go](https://golang.org/)
Hay dos formas:
1. Ve a [https://golang.org/dl](https://golang.go/dl)
2. Elige la versión Linux
3. Ejecuta el instalador
4. Si estas usando snap: avanza hasta el paso 5.
```bash
sudo snap install go --classic
```
## 4. Copia Go en el directorio apropiado
1. Encuentra el nombre del archivo descargado
2. Usa el nombre de ese archivo para descomprimirlo
```bash
gofile="BORRA_ESTO_Y_ESCRIBE_EL_NOMBRE_DEL_ARCHIVO_DESCARGADO (sin la extension)"
tar -C /usr/local -xzf ~/Downloads/$gofile
```
## 5. Añade los executables de Go a tu PATH
1. Añade el directorio `go/bin` al `$PATH` para poder ejecutar los comandos principales de Go.
```bash
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
```
2. Añade el directorio `$HOME/go/bin` a tu `$PATH`
```bash
echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.profile
```
## Instala Las Herramientas de Go
- Estas son utiles herramientas que ayudan a facilitar el desarrollo (como goimports)
- `go get` no puede ser usado sin haber instalado un programa de control de versiones como Git.
- Esto creara un directorio llamado `~/go` donde se descargaran las herramientas
- Este directorio tambien es el lugar donde deberias poner tu codigo. (Si no vas a usar los modulos de Go)
```bash
go get -v -u golang.org/x/tools/...
```
## Instala El Editor Visual Studio Code
Nota: Puedes usar otro editor de codigo si quieres. Igualmente, el curso usa Visual Studio Code (VS Code).
1. Abre la aplicación "Ubuntu Software"
2. Busca "VSCode" y clicka en el boton de Instalar
## PASO OPCIONAL
1. Crea un archivo llamado `hola.go` en un nuevo directorio alejado de `$GOPATH`
```bash
cat < hola.go
package main
import "fmt"
func main() {
fmt.Println("hola gopher!")
}
EOF
```
2. Ejecuta el programa
```bash
go run hola.go
Deberia imprimir: hola gopher!
```
## Eso es todo! Disfrutad! 🤩
> Para mas tutoriales: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2021 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click aqui para leer la licencia.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/spanish/01-empecemos/instalacion-windows.md
================================================
# Instalación Windows
## NOTA
Si tienes el administrador de paquetes [chocolatey.org](https://chocolatey.org/) puedes instalar Go facilmente con este comando:
```bash
choco install golang
```
### 1. Instala el editor [Visual Studio Code](https://code.visualstudio.com)
1. Instálalo pero no lo abras todavia
2. Ve a: [https://code.visualstudio.com](https://code.visualstudio.com)
3. Elige la versión para Windows
4. Ejecuta el instalador
## 2. Instala Git
1. Descarga y ejecuta el instalador: Ve a: [https://gitforwindows.org](https://gitforwindows.org)
2. Elige VSCode como editor por defecto
3. Marca todas las casillas
4. Elige: "Utilizar Git desde la Consola de Comandos de Windows"
5. Codificaciones: Elige la opción: \_"Dejar como esta..."
## 3. Instala [Go](https://golang.org/)
1. Ve a: [https://golang.org/dl](https://golang.org/dl)
2. Elige Windows y descargalo
3. Ejecuta el instalador
## 4. Configura Visual Studio Code
1. Abre VS Code; haz click en la pestaña de extensiones situada a la izquierda, busca "go" e instálalo
2. Cierra VS Code por completo y ábrelo de nuevo
3. Ve al menu 'Ver' y selecciona **Paleta de Comandos**
1. O simplemente presiona: `ctrl+shift+p`
2. Escribe: `go install`
3. Elige: _"Go: Install/Update Tools"_
4. Marca todas las casillas
## 5. Usando Git-Bash
- En este curso hare uso de comandos bash. Bash es simplemente una linea de comandos usada en OS X y en Linux. Es una de las interfaces de linea de comandos mas populares. Asi que, si quieres usarla tambien, en vez de usar la linea de comandos por defecto de Windows, puedes usar Git-Bash. Con ella puedes escribir comandos tanto de OS X como de Linux.
- Si no quieres hacer uso de Git-Bash no pasa nada, depende de ti. Pero ten en cuenta que yo hare uso constante de comandos bash.
- Tambien puedes utilizar algo mas potente que Git-Bash como podria ser el: [Subsistema de Linux para Windows](https://docs.microsoft.com/es-es/windows/wsl/install-win10)
- **Para usar git bash sigue los siguientes pasos:**
1. Busca git bash desde la barra de busqueda
2. O, si hay un icono en tu escritorio, clicka en el
3. Usa git bash por defecto en VS Code:
1. Abre VS Code
2. Ves a la **Paleta de Comandos**
1. Escribe: `terminal`
2. Elige: _"Terminal: Terminal por Defecto"_
3. Y elige: _"Git Bash"_
3. **NOTA:** Normalmente, puedes encontrar tus archivos en `c:\`, pero, cuando estas usando git bash los encontraras en `/c/`, que es el mismo directorio pero mas abreviada
## Eso es todo! Disfrutad! 🤩
> Para mas tutoriales: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2021 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click aqui para leer la licencia.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/spanish/02-tu-primer-programa/README.md
================================================
# Escribe Tu Primer Programa Usando Go
¡Hola!
Puedes guardar este documento después de ver los vídeos de esta sección en particular.
Tambien puedes imprimirla y usarlo junto a los vídeos de esta sección.
¡Disfruta!
---
## COMANDOS DE LA CONSOLA DE COMANDOS
Entra al siguiente directorio: `cd directoryPath`
- **WINDOWS:**
- Muestra los archivos en ese directorio: `dir`
- **OS X distribuciones linux:**
- Muestra los archivos en ese directorio: `ls`
## COMPILANDO Y EJECUTANDO PROGRAMAS CON GO:
- **Compilando Un Programa En Go:**
- Dentro del directorio del programa, escribe:
- `go build`
- **Ejecuta Un Programa En Go:**
- Dentro del directorio del programa, escribe:
- `go run main.go`
## QUE ES EL $GOPATH?
- _$GOPATH_ es una variable de entorno que apunta a un directorio donde los archivos descargados por Go y los tuyos propios se encuentran.
- **En Windows**, Esta en: `%USERPROFILE%\go`
- **En OS X y en Linux**, Esta en: `~/go`
- **NOTE:** Nunca introduzcas tu `GOPATH` de forma manual. Siempre se encuentra en el directorio de usuario por defecto.
- **GOPATH tiene tres directorios:**
- **src:** Contiene los archivos fuente para tus paquetes o para otros paquetes que descargues. Puedes compilar y ejecutar programas mientras te encuentres en el directorio del programa.
- **pkg:** Contiene paquetes de archivos compilados. Go usa esto para compilar de forma eficiente.
- **bin:** Contiene programas compilados y ejecutables. Cuando usas el comando go install en el directorio de un programa, Go creara un archivo ejecutable en el mismo.
- _Quizas quieras añadir esto a tu variable de entorno`PATH` si no esta ahi._
## DONDE DEBERÍA PONER MIS ARCHIVOS FUENTE?
- `$GOPATH/src/github.com/yourUsername/programDirectory`
- **Ejemplo:**
- Mi nombre en github es: inancgumus
- Asi que añado todos mis programas bajo: `~/go/src/github.com/inancgumus/`
- Asi que, digamos que tengo un programa llamado hello, este se encontrará en: `~/go/src/github.com/inancgumus/hello`
## TU PRIMER PROGRAMA!
- **Crea Los Directorios:**
- **OS X & Linux (o git bash):**
- Crea un nuevo directorio:
- `mkdir -p ~/go/src/yourname/hello`
- Ve a ese directorio:
- `cd ~/go/src/yourname/hello`
- **Windows:**
- Crea un nuevo directorio:
- `mkdir c:\Go\src\yourname\hello`
- Ve a ese directorio:
- `cd c:\Go\src\yourname\hello`
- Crea un nuevo archivo usando `code main.go` Visual Studio Code.
- Añade el siguiente codigo y guardalo.
- Vuelve a la consola de comandos.
- Ejecútalo con el comando: `go run main.go`
```go
package main
import "fmt"
func main() {
fmt.Println("Hi! I want to be a Gopher!")
}
```
Eso es todo! Disfruta!
## NOTA:
- Hay un nuevo _Go Modules_ que te permite ejecutar tus programas en cualquier directorio de tu elección. Es todavia una caracteristica experimental, cuando se estabilize actualizare el curso para incluir los Go Modules.
> Para mas tutoriales: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2021 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click aqui para leer la licencia.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/spanish/02-tu-primer-programa/anotaciones-ejemplo-programa-go.md
================================================
# Anotaciones Ejemplo Programa en Go
```go
// package main es un paquete especial
// le permite a Go crear un archivo ejecutable
package main
/*
Esto es un comentario multilinea.
la palabra import hace que otro paquete este disponible
para este "archivo" .go.
import "fmt" te permite acceder a la funcionaliddad del paquete fmt
en este archivo.
*/
import "fmt"
// "func main" es especial.
//
// Go tiene que saber por donde empezar
//
// func main crea un punto de inicio para Go
//
// Después de compilar el codigo,
// Go ejecutará esta función primero.
func main() {
// después del: import "fmt"
// La función Println del paquete "fmt" estará disponible
// Lee sobre ella escribiendo los siguiente en la consola:
// go doc -src fmt Println
// Println es simplemente una función exportada de:
// "fmt" package
// Para poder exportar una función tendrás que escribir el
// primer caracter del nombre de la función en mayúscula.
fmt.Println("Hello Gopher!")
// Go no puede llamar a la función Println por si mismo.
// Por eso la tienes que llamar aqui.
// Solo llama a la `func main` de forma automatica.
// -----
// Go soporta caracteres unicode en cadenas de texto literal
// y tambien en el codigo fuente: KÖSTEBEK!
//
// Porque: Literal ~= Codigo Fuente
}
```
> Para mas tutoriales: [https://blog.learngoprogramming.com](https://blog.learngoprogramming.com)
>
> Copyright © 2021 Inanc Gumus
>
> Learn Go Programming Course
>
> [Click aqui para leer la licencia.](https://creativecommons.org/licenses/by-nc-sa/4.0/)
================================================
FILE: translation/spanish/02-tu-primer-programa/ejercicios/01-imprimiendo-nombres/main.go
================================================
// Copyright © 2021 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para mas tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en Twitter : https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EJERCICIO: Imprimir nombres
//
// Imprime tu nombre y el de tu mejor amigo usando
// Println dos veces
//
// RESULTADO ESPERADO
// TuNombre
// ElNombreDeTuMejorAmigo
//
// BONUS
// Usa `go run` primero.
// Y despues de eso usa `go build` y ejecuta tu programa.
// ---------------------------------------------------------
func main() {
// ?
// ?
}
================================================
FILE: translation/spanish/02-tu-primer-programa/ejercicios/01-imprimiendo-nombres/solucion/main.go
================================================
// Copyright © 2021 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para mas tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en Twitter : https://twitter.com/inancgumus
package main
import "fmt"
// go run main.go
// go build
// ./solution
func main() {
fmt.Println("Nikola")
fmt.Println("Thomas")
}
================================================
FILE: translation/spanish/02-tu-primer-programa/ejercicios/02-imprimiendo-gopath/ejercicio.md
================================================
- **Ejercicio: Imprime tu GOPATH**
Imprime tu GOPATH usando la herramienta `go env`
- **RESULTADO ESPERADO:**
La ruta física de la carpeta que hace referencia al `$GOPATH`
================================================
FILE: translation/spanish/02-tu-primer-programa/ejercicios/02-imprimiendo-gopath/solucion/solucion.md
================================================
* **Debes de escribir esto en tu consola de comandos:**
```bash
go env GOPATH
```
================================================
FILE: translation/spanish/02-tu-primer-programa/ejercicios/README.md
================================================
1. **Imprime tu nombre y el nombre de tu mejor amigo** usando Println dos veces. [Échale un vistazo a este ejercicio](https://github.com/inancgumus/learngo/tree/master/translation/spanish/02-tu-primer-programa/ejericios/01-imprimir-nombres).
2. **Imprime tu GOPATH** usando la herramienta `go env` [Échale un vistazo a este ejercicio](https://github.com/inancgumus/learngo/tree/master/translation/spanish/02-tu-primer-programa/ejercicios/02-imprimir-gopath).
3. **Saludate a ti mismo.**
1. Complila tu programa usando `go build`
2. **Envíaselo a tu amigo**
Debería tener el mismo sistema operativo.
Por ejemplo si estás usando Windows envíaselo a un amigo que también tenga Windows.
3. **Envíaselo a un amigo con un sistema operativo diferente**
Deberías compilar el programa especificamente para su sistema operativo.
**Crea un ejecutable para OS X:**
`GOOS=darwin GOARCH=386 go build`
**Crea un ejecutable para Windows:**
`GOOS=windows GOARCH=386 go build`
**Crea un ejecutable para Linux:**
`GOOS=linux GOARCH=arm GOARM=7 go build`
**Puedes encontrar una lista completa aquí:**
https://golang.org/doc/install/source#environment
**NOTA:** Si estás usando la consola de comandos o PowerShell, quizás necesites usarlo de la siguiente forma:
`cmd /c "set GOOS=darwin GOARCH=386 && go build"`
4. **Llama a [Print](https://golang.org/pkg/fmt/#Print) en vez de a [Println](https://golang.org/pkg/fmt/#Println)** y observa que pasa.
5. **Llama a [Println](https://golang.org/pkg/fmt/#Println) o a [Print](https://golang.org/pkg/fmt/#Print) con multiples valores** separados por comas.
6. **Elimina las comillas dobles de una cadena de texto literal** y observa que pasa.
7. **Mueve tanto el package como import** al final del archivo y observa que pasa.
8. **[Lee la documentación en línea](https://golang.org/pkg)**.
1. Échale un vistazo a qué son los packages y qué es lo que hacen.
2. Mira su codigo fuente clickeando sobre su titulo.
3. No tienes porque entenderlo todo, simplemente hazlo. Esto te dará un empujón de cara a las siguientes clases.
9. También, puedes tomar **un tour con Go**: https://tour.golang.org/
1. Échale un vistazo rápido. Mira las caracteristicas del lenguaje.
2. Hablaremos de ellas proximamente.
================================================
FILE: translation/spanish/02-tu-primer-programa/main.go
================================================
// Copyright © 2021 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para mas tutoriales: https://learngoprogramming.com
// Clases particulares: https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
// package main es un paquete especial
// le permite a Go crear un archivo ejecutable
package main
/*
Esto es un comentario multilinea.
la palabra import hace que otro paquete este disponible
para este "archivo" .go.
import "fmt" te permite acceder a la funcionaliddad del paquete fmt
en este archivo.
*/
import "fmt"
// "func main" es especial.
//
// Go tiene que saber por donde empezar
//
// func main crea un punto de inicio para Go
//
// Después de compilar el codigo,
// Go ejecutará esta función primero.
func main() {
// después del: import "fmt"
// La función Println del paquete "fmt" estará disponible
// Lee sobre ella escribiendo los siguiente en la consola:
// go doc -src fmt Println
// Println es simplemente una función exportada de:
// "fmt" package
// Para poder exportar una función tendrás que escribir el
// primer caracter del nombre de la función en mayúscula.
fmt.Println("Hello Gopher!")
// Go no puede llamar a la función Println por si mismo.
// Por eso la tienes que llamar aqui.
// Solo llama a la `func main` de forma automatica.
// -----
// Go soporta caracteres unicode en cadenas de texto literal
// y tambien en el codigo fuente: KÖSTEBEK!
//
// Porque: Literal ~= Codigo Fuente
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/01-paquetes/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("Bye!")
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/01-paquetes/hey.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hey() {
fmt.Println("Hey!")
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/01-paquetes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
// Puedes acceder a funciones desde otros archivos
// los cuales esten en el mismo paquete
// Por ejemplo, `main()` puede acceder a `bye()` y `hey()`
// Porque bye.go, hey.go y main.go
// estan en el mismo paquete.
bye()
hey()
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/02-funciones/01-funciones/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
// Librerias importadas
import "fmt"
// variables del paquete
const ok = true
// función del paquete
func main() { // Empieza el bloque de la función
var hola = "Hola"
// hola y ok son visibles aquí
fmt.Println(hola, ok)
} // Termina el bloque de la función
================================================
FILE: translation/spanish/03-paquetes-y-funciones/02-funciones/02-bloque-de-funcion/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
func nope() { // Empieza el bloque de la función
// hola y ok solamente son visibles aquí
const ok = true
var hola = "Hola"
_ = hola
} // Termina el bloque de la función
func main() { // Empieza el bloque de la función
// hola y ok no son visibles aquí
// ERROR:
// fmt.Println(hola, ok)
} // Termina el bloque de la función
================================================
FILE: translation/spanish/03-paquetes-y-funciones/02-funciones/03-funciones-anidadas/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
// No hable de esto en la lectura
// quiero dejarlo aqui como una pequeña nota
// Por favor revisalo.
var declarameOtraVez = 10
func anidado() { // Empieza el bloque de la función
// declara las misma variables
// ambas pueden existir juntas
// Esta solo pertenece a esta función
// la variable del paquete sigue intacta
var declarameOtraVez = 5
fmt.Println("Dentro del anidado:", declarameOtraVez)
} // Termina el bloque de la función
func main() { // Empieza el bloque de la función
fmt.Println("Dentro de main:", declarameOtraVez)
anidado()
// a nivel paquete, declarameOtraVez no fue alterado
// desde el cambio dentro de la funcion anidado
fmt.Println("Dentro de main:", declarameOtraVez)
} // Termina el bloque de la función
================================================
FILE: translation/spanish/03-paquetes-y-funciones/02-funciones/04-funcion-del-paquete/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("Bye!")
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/02-funciones/04-funcion-del-paquete/hey.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hey() {
fmt.Println("Hey!")
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/02-funciones/04-funcion-del-paquete/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
//Dos archivos pertenecen al mismo paquete
// llamando `bye()` de bye.go a aqui
bye()
}
// Ejercicio: Quita los comentarios de la siguiente función y analiza el error
// func bye() {
// fmt.Println("Bye!")
// }
// ***** EXPLICACIÓN *****
//
// ERROR: "bye" function "redeclared"
// in "this block"
//
// "this block" significa = "main package"
//
// "redeclared" significa = Estas usando el mismo nompre en la funcion otra vez
//
// La función main package es:
// todo el codigo que esta en el mismo paquete main
================================================
FILE: translation/spanish/03-paquetes-y-funciones/03-importando/01-funcion-del-archivo/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
// quita los comentarios del codigo para ver el error
// (Solo quita las // del codigo en las 3 lineas siguientes)
// Este archivo no puede ver los nombres importados de main.go ("fmt")
// porque los nombres importados pertenecen a la funcion del archivo (librerias)
// func bye() {
// fmt.Println("Bye!")
// }
================================================
FILE: translation/spanish/03-paquetes-y-funciones/03-importando/01-funcion-del-archivo/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
fmt.Println("Hello!")
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/03-importando/02-renombrando/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
f "fmt"
)
func main() {
fmt.Println("Hello!")
f.Println("There!")
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/ejercicios/01-paquetes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EJERCICIO: Usa tu propio paquete
//
// Crea algunos archivos Go y llama sus funciónes desde
// la funcion main
//
// 1- Crea los archivos main.go, greet.go y bye.go
// 2- En main.go: Llama a las funciones greet y bye.
// 3- Corre `main.go`
//
// PISTA
// La funcion greet deberia de estar en greet,go
// La funcion bye deberia de estar en bye.go
//
// SALIDA ESPERADA
// Hola!!
// Adios!!
// ---------------------------------------------------------
func main() {
// Llama a las funciones de los otros archivos aqui.
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/ejercicios/01-paquetes/solucion/bye.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func bye() {
fmt.Println("adios!!")
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/ejercicios/01-paquetes/solucion/greet.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
func greet() {
fmt.Println("hola!!")
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/ejercicios/01-paquetes/solucion/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
func main() {
greet()
bye()
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/ejercicios/02-scopes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EJERCICIO: Prueba las funciones
//
// 1. Crea 2 archivos: main.go y printer.go
//
// 2. En printer.go:
// 1. Crea una funcion llamada hello
// 2. Dentro de la funcion hello, imprime tu nombre
//
// 3. En main.go:
// 1. Crea la tipica funcion func main
// 2. Llama a tu funcion solo usando su nombre: hello
// 3. Crea una funcion llamda bye
// 4. Dentro de la funcion bye, imprime "bye bye"
//
// 4. En printer.go:
// 1. Llama a la funcion bye desde dentro de la funcion hello
// ---------------------------------------------------------
func main() {
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/ejercicios/02-scopes/solucion/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// Como puedes verm no necesito importar el un paquete
// y puedo llamar a la funcion 'hello' aqui
//
// Esto es porque las funciones de paquetes (librerias)
// estan compartidas en el mismo paquete
hello()
// pero aqui no puedo acceder al paquete fmt sin importarlo
//
// Esto es porque esta en la funcion del archivo printer.go
// lo importa
//
// esta funcion main puede tambien llamar a la funcion bye aqui
// bye()
}
// printer.go puede llamar a esta funcion
//
// Esto es porque la funcion bye esta en la funcion del paquete (libreria)
// del paquete main ahora
// .
//
// La funcion main tambien puede llamar aqui.
func bye() {
fmt.Println("bye bye")
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/ejercicios/02-scopes/solucion/printer.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import "fmt"
func hello() {
// Solo este archivo puede acceder a la funcion de paquete fmt
// cuando otros ya lo hiciero, ellos tamvien pueden acceder
// Su propio 'fmt' "name"
fmt.Println("hi! this is inanc!")
bye()
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/ejercicios/03-importando/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
// ---------------------------------------------------------
// EJERCICIO: Renombra las importaciones
//
// 1- Importa el paquete fmt tres veces con diferentes nombres
// 2- Imprime algunos mensajes usando esas importaciones
//
// SALIDA ESPERADA
// hello
// hey
// hi
// ---------------------------------------------------------
// ?
// ?
// ?
func main() {
// ?
// ?
// ?
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/ejercicios/03-importando/solucion/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// Licencia: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Para más tutoriales : https://learngoprogramming.com
// Clases particulares : https://www.linkedin.com/in/inancgumus/
// Sigueme en twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
f "fmt"
fm "fmt"
)
func main() {
fmt.Println("hello")
f.Println("hey")
fm.Println("hi")
}
================================================
FILE: translation/spanish/03-paquetes-y-funciones/ejercicios/README.md
================================================
1. **[Usa tus propios paquetes](https://github.com/inancgumus/learngo/tree/master/03-packages-and-scopes/exercises/01-packages)**
Crea algunos archivos Go y llama sus funciones desde la función main.
2. **[Prueba las funciones](https://github.com/inancgumus/learngo/tree/master/03-packages-and-scopes/exercises/02-scopes)**
Aprende los efectos del acceso de funciones de paquetes ó Librerias.
3. **[Renombra las importaciones](https://github.com/inancgumus/learngo/tree/master/03-packages-and-scopes/exercises/03-importing)**
Importa los mismos paquetes usando diferentes nombres.
================================================
FILE: translation/spanish/03-paquetes-y-funciones/preguntas/01-paquetes-A/README.md
================================================
## ¿Dónde almacenar los archivos de código fuente que pertenecen a un paquete?
1. Cada archivo debe ir a un directorio diferente
2. En un solo directorio *CORRECTO*
## ¿Por qué se utiliza una cláusula de paquete en un archivo de código fuente de Go?
1. Se usa para importar un paquete.
2. Se utiliza para informarle a Go que el archivo pertenece a un paquete *CORRECTO*
3. Se usa para declarar una nueva función
> **1:** `import` declaración hace eso.
>
>
> **3:** `func` declaración hace eso.
>
>
## ¿Dónde debería poner el `package clause` en un archivo de código fuente de Go?
1. Como primer código en un archivo de código fuente de Go *CORRECTO*
2. Como último código en un archivo de código fuente de Go
3. Puedes ponerlo en cualquier lugar
## ¿Cuántas veces puede usar`package clause` para un solo archivo de código fuente?
1. Una vez *CORRECTO*
2. Ninguna
3. Varias veces
## ¿Cuál es el uso correcto de`package clause`?
1. `my package`
2. `package main`
3. `pkg main`
## ¿Cual es la correcta?
1. Todos los archivos pertenecen al mismo paquete no pueden llamar a las funciones de los demás
2. Todos los archivos pertenecen al mismo paquete pueden llamar a las funciones de los demás *CORRECTO*
## ¿Cómo ejecutar varios archivos Go?
1. go run *.*go
2. go build *go
3. go run go
4. go run *.go *CORRECTO*
> **4:** También puede llamarlo como (asumiendo que hay file1.go file2.go y file3.go en el mismo directorio): vaya a ejecutar file1.go file2.go file3.go
>
>
================================================
FILE: translation/spanish/03-paquetes-y-funciones/preguntas/02-paquete-B/README.md
================================================
## ¿Cuál de los siguientes es un tipo de paquete correcto en Go?
* Paquete vacio
* Paquete ejecutable *CORRECTO*
* Paquete transferible
* Paquete de libreria
## ¿Qué tipo de paquete `go run` puede ejecutar?
* Paquete vacio
* Paquete ejecutable *CORRECTO*
* Paquete transferible
* Paquete de libreria
## ¿Qué tipo de paquete `go run` puede compilar?
* Paquete vacio
* Paquete temporal
* Ambos paquetes ejecutables y de libreria *CORRECTO*
* Paquete transferible
## ¿Cuál es un paquete ejecutable?
* `package main` con `func main` *CORRECTO*
* `package Main` con `func Main`
* `package exec` con `func exec`
## ¿Cuál es un paquete de libreria?
* `main package`
* `package lib` *CORRECTO*
* `func package`
* `package main` con `func main`
## ¿Qué paquete se utiliza para un programa Go ejecutable?
* Paquete vacio
* Paquete ejecutable *CORRECTO*
* Paquete transferible
* Paquete de libreria
## ¿Qué paquete se utiliza para la reutilización y se puede importar?
* Paquete vacio
* Paquete ejecutable
* Paquete transferible
* Paquete de libreria *CORRECTO*
================================================
FILE: translation/spanish/03-paquetes-y-funciones/preguntas/03-funciones/README.md
================================================
## ¿Qué es una funcion?
* Bloque de código ejecutable
* La visibilidad de los nombres declarados **CORRECTO**
* Determina qué ejecutar
```go
package awesome
import "fmt"
var enabled bool
func block() {
var counter int
fmt.Println(counter)
}
```
## ¿Qué nombre a continuación tiene la fuincion del paquete(libreria)?
1. awesome
2. fmt
3. enabled **CORRECTO**
4. counter
> **3:** Eso es correcto.`enabled` enabledestá fuera de cualquier función, por lo que es un nombre de ámbito de paquete. La funcion `block()` también tiene el alcance del paquete; también está fuera de cualquier función.
>
>
## ¿Qué nombre a continuación tiene la funcion del archivo?
1. awesome
2. fmt **CORRECTO**
3. enabled
4. block()
5. counter
> **2:** Eso es correcto. Los nombres de los paquetes importados tienen un ámbito de archivo. Y solo se pueden usar dentro del mismo archivo.
>
>
## ¿Qué nombre a continuación está en el alcance de la función block ()?
1. awesome
2. fmt
3. enabled
4. block()
5. counter **CORRECTO*
> **5:** Eso es correcto. `counter` se declara dentro de la funcion `block()` por lo que está en el alcance del bloque func. Fuera de la funcion `block()`, otro código no puede verlo.
>
>
## ¿Puede `block()` ver el nombre `enabled`?
1. Sí: está en el alcance del paquete **CORRECTO**
2. No: está en el alcance del archivo
3. No: está en el alcance del bloque de block ()
> **1:** Todo el código dentro del mismo paquete puede ver todos los demás nombres declarados a nivel de paquete.
>
>
## ¿Pueden otros archivos en el paquete `awesome` ver el nombre de `counter`?
1. Si
2. No: está en la funcion del paquete
3. No: está en la funcion del archivo
4. No: está en la funcion del block() **CORRECTO**
> **4:** Eso es correcto. Ninguno de los otros códigos puede ver los nombres dentro de la funcion `block()` .Solo el código dentro de la funcion `block()` puede verlos (Solo hasta cierto punto. Por ejemplo: Dentro del bloque, el código solo puede ver las variables declaradas antes).
>
## ¿Pueden otros archivos en el paquete `awesome` ver el nombre de`fmt` ?
1. Si
2. No: está en la funcion del paquete
3. No: está en la funcion del archivo **CORRECTO**
4. No: está en la funcion del bloque()
> **3:** Solo el mismo archivo puede ver los paquetes importados, no los otros archivos, ya sea que estén en el mismo paquete o no.
>
>
## ¿Qué sucede si declaras el mismo nombre en el mismo ámbito que este?
```go
package awesome
import "fmt"
// declared twice in the package scope
var enabled bool
var enabled bool
func block() {
var counter int
fmt.Println(counter)
}
```
1. El nombre recién declarado prevalecerá sobre el anterior.
2. No puedo hacer eso. Ya se ha declarado en la funcion del paquete. *CORRECTO*
3. No puedo hacer eso. Ya se ha declarado en la funcion del archivo.
> **2:** Eso es correcto. No puede declarar el mismo nombre en el mismo ámbito. Si pudiera hacerlo, ¿cómo volvería a acceder a él? ¿O a cuál?
>
>
## ¿Qué sucede si declaras el mismo nombre en otro ámbito como este?:
```go
package awesome
import "fmt"
// declared at the package scope
var enabled bool
func block() {
// also declared in the block scope
var enabled bool
var counter int
fmt.Println(counter)
}
```
1. El nombre recién declarado prevalecerá sobre el anterior. *CORRECTO*
2. No puedo hacer eso. Ya se ha declarado en la funcion del paquete.
3. No puedo hacer eso. Ya se ha declarado en la funcion del archivo.
> **1:** En realidad, puede declarar el mismo nombre en los ámbitos internos de esta manera. La funcion `block()` está dentro de su paquete. Esto significa que puede acceder al alcance de su paquete (pero no al revés). Entonces, la funcion `block()`de 'está bajo el alcance de su paquete. Esto significa que puede volver a declarar el mismo nombre. Anulará el nombre del ámbito principal. Ambos pueden existir juntos. Consulte el ejemplo en el repositorio de cursos para averiguarlo.
>
>
================================================
FILE: translation/spanish/README.md
================================================
# Aprendiendo a usar Go con ejemplos, ejercicios y puzzles
La mejor forma de aprender es haciendo. En este repositorio encontrarás miles de ejemplos, ejercicios y puzzles hechos con Go. Inicialmente creé este repositorio para mi **[Go: Bootcamp Course](https://udemy.com/course/learn-go-the-complete-bootcamp-course-golang/?referralCode=5CE6EB34E2B1EF4A7D37)**. Tiempo después seguí añadiendo ejercicios y quise que todo programador no inscrito a mi curso también pudiese aprender de forma gratuita. Así que aquí está. Disfrutad.
## ❤️ Ayuda a otros desarrolladores
Compartir es gratis pero cuidar no tiene precio, [así que por favor haz click aquí](https://twitter.com/intent/tweet?text=I%27m%20learning%20%23golang%20with%201000%2B%20hand-crafted%20examples%2C%20exercises%2C%20and%20quizzes.&url=https://github.com/inancgumus/learngo&via=inancgumus) y comparte este repositorio en Twitter.
## Mantente en contacto
* **[Sígueme en Twitter](https://twitter.com/inancgumus)**
_Usualmente twiteo trucos y consejos sobre Go._
[](https://twitter.com/inancgumus)
* **[Suscríbete a mi Newsletter](https://eepurl.com/c4DMNX)**
_Recibe actualizaciones de mi parte._
* **[Lee mi Blog](https://blog.learngoprogramming.com)**
_Seguido por más de 5 mil desarrolladores y con decenas de artículos ilustrados sobre Go._
* **[Mira mi canal de Youtube](https://www.youtube.com/channel/UCYxepZhtnFIVRh8t5H_QAdg?view_as=subscriber)**
---
### Licencia
Todos los materiales están protegidos bajo la licencia Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
================================================
FILE: x-tba/README.md
================================================
This folder contains directories and files that belong to unreleased lectures and sections. So, it's your responsibility to do something with those; they can work or cannot, they are not stable. I change these files all the time. This is my scratch-pad.
================================================
FILE: x-tba/foundations/01-print-args/01-printf/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
// zero-values
var (
planet string
distance int
orbital float64
hasLife bool
)
// assignment
planet = "venus"
distance = 261
orbital = 224.701
hasLife = false
// var (
// planet = "venus"
// distance = 261
// orbital = 224.701
// hasLife = false
// )
distance += 5
distance *= 2
distance++
distance--
orbital++
// orbital *= 10
const constFactor = 10
orbital *= constFactor
factor := 10
// orbital *= factor
orbital *= float64(factor)
// swiss army knife %v verb
fmt.Printf("Planet: %v\n", planet)
fmt.Printf("Distance: %v millions kms\n", distance)
fmt.Printf("Orbital Period: %v days\n", orbital)
fmt.Printf("Does %v have life? %v\n", planet, hasLife)
// argument indexing - indexes start from 1
fmt.Printf(
"%v is %v away. Think! %[2]v kms! %[1]v OMG.\n",
planet, distance,
)
// why use other verbs than? because: type-safety
// uncomment to see the warnings:
//
// fmt.Printf("Planet: %d\n", planet)
// fmt.Printf("Distance: %s millions kms\n", distance)
// fmt.Printf("Orbital Period: %t days\n", orbital)
// fmt.Printf("Does %v has life? %f\n", planet, hasLife)
// correct verbs:
// fmt.Printf("Planet: %s\n", planet)
// fmt.Printf("Distance: %d millions kms\n", distance)
// fmt.Printf("Orbital Period: %f days\n", orbital)
// fmt.Printf("Does %s has life? %t\n", planet, hasLife)
// precision
fmt.Printf("Orbital Period: %f days\n", orbital)
fmt.Printf("Orbital Period: %.0f days\n", orbital)
fmt.Printf("Orbital Period: %.1f days\n", orbital)
fmt.Printf("Orbital Period: %.2f days\n", orbital)
}
================================================
FILE: x-tba/foundations/01-print-args/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
fmt.Println("There are", len(os.Args)-1, "people !")
fmt.Println("Hello great", os.Args[1], "!")
fmt.Println("Hello great", os.Args[2], "!")
fmt.Println("Hello great", os.Args[3], "!")
fmt.Println("Hello great", os.Args[4], "!")
fmt.Println("Hello great", os.Args[5], "!")
fmt.Println("Nice to meet you all.")
path := `c:\program files\duper super\fun.txt
c:\program files\really\funny.png`
fmt.Println(path)
}
================================================
FILE: x-tba/foundations/02-variables/01-basics/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
)
func main() {
// var (
// name string
// name2 string
// name3 string
// )
// var name, name2, name3 string
// name = os.Args[1]
// name2 = os.Args[2]
// name3 = os.Args[3]
// name := os.Args[1]
// name2 := os.Args[2]
// name3 := os.Args[3]
name, name2, name3 := os.Args[1], os.Args[2], os.Args[3]
fmt.Println("Hello great", name, "!")
fmt.Println("And hellooo to you magnificient", name2, "!")
fmt.Println("Welcome", name3, "!")
// changes the name, declares the age with 131
name, age := "bilbo baggins", 131 // unknown age!
fmt.Println("My name is", name)
fmt.Println("My age is", age)
fmt.Println("And, I love adventures!")
}
================================================
FILE: x-tba/foundations/02-variables/02-short-discard/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
"os"
"path"
"strconv"
)
func main() {
var radius, area float64
radius, _ = strconv.ParseFloat(os.Args[1], 64)
area = 4 * math.Pi * math.Pow(radius, 2)
// area := 4 * math.Pi * math.Pow(radius, 2)
fmt.Printf("radius: %g -> area: %.2f\n",
radius, area)
dir, _ := path.Split("secret/file.txt")
fmt.Println(dir)
color, color2 := "red", "blue"
color, color2 = color2, color
fmt.Println(color, color2)
}
================================================
FILE: x-tba/foundations/02-variables/03-conversion/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
min := int8(127)
max := int16(1000)
fmt.Println(max + int16(min))
// EXPLANATION
//
// `int8(max)` destroys the information of max
// It reduces it to 127
// Which is the maximum value of int8
//
// Correct conversion is int16(min)
// Because, int16 > int8
// When you do so, min doesn't lose information
//
// You will learn more about this in
// the "Go Type System" section.
}
================================================
FILE: x-tba/foundations/02-variables/types/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
"os"
"runtime"
"time"
)
func main() {
// int, float64, bool, string
var (
cpus int
path, dir string
max float64
)
cpus = runtime.NumCPU()
path = os.Getenv("PATH")
max = math.Max(1.5, 2.5)
dir, _ = os.Getwd()
now := time.Now()
// cpus := runtime.NumCPU()
// path := os.Getenv("PATH")
// max := math.Max(1.5, 2.5)
// dir, _ := os.Getwd()
// dir = `"` + dir + `"`
// dir = strconv.Quote(dir)
// cpus++
// cpus *= 2.5
// max++
// max /= 2.5
// paths = strings.Split(path, ":")
// path = paths[0]
fmt.Printf("# of CPUS : %d\n", cpus)
fmt.Printf("Path : %s\n", path)
fmt.Printf("max(1.5, 2.5) : %g\n", max)
fmt.Printf("Current Directory: %s\n", dir)
fmt.Printf("Current Time : %s\n", now)
}
================================================
FILE: x-tba/foundations/03-if-switch-loop/01-for-crunch-the-primes/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
// go run . {1..100}
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
const usageMsg = `Type a couple of unique numbers.
Separate them with spaces.`
// remember [1:] skips the first argument
args := os.Args[1:]
if len(args) == 0 {
fmt.Println(usageMsg)
return
}
main:
for _, arg := range args {
n, err := strconv.Atoi(arg)
if err != nil {
// skip non-numerics
continue
}
switch {
// prime
case n == 2, n == 3:
fmt.Print(n, " ")
continue
// not a prime
case n <= 1, n%2 == 0, n%3 == 0:
continue
}
for i, w := 5, 2; i*i <= n; {
// not a prime
if n%i == 0 {
continue main
}
i += w
w = 6 - w
}
// all checks ok: it's a prime
fmt.Print(n, " ")
}
fmt.Println()
}
================================================
FILE: x-tba/foundations/03-if-switch-loop/02-switch-months/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strings"
"time"
)
func main() {
if len(os.Args) != 2 {
fmt.Println("Give me a month name")
return
}
year := time.Now().Year()
leap := year%4 == 0 && (year%100 != 0 || year%400 == 0)
days, month := 28, os.Args[1]
switch strings.ToLower(month) {
case "april", "june", "september", "november":
days = 30
case "january", "march", "may", "july",
"august", "october", "december":
days = 31
case "february":
if leap {
days = 29
}
default:
fmt.Printf("%q is not a month.\n", month)
return
}
fmt.Printf("%q has %d days.\n", month, days)
}
================================================
FILE: x-tba/foundations/03-if-switch-loop/03-math-table-if-switch-loop/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
const (
validOps = "* / + - mul div add sub"
usageMsg = "Usage: [valid ops: " + validOps + "] [size]"
sizeMissingMsg = "Size is missing\n" + usageMsg
invalidOpMsg = `Invalid operator.
Valid ops one of: ` + validOps
)
func main() {
// CHECK THE ARGUMENTS
args := os.Args[1:]
if l := len(args); l == 1 {
fmt.Println(sizeMissingMsg)
return
} else if l < 1 {
fmt.Println(usageMsg)
return
}
size, err := strconv.Atoi(args[1])
if err != nil || size <= 0 {
fmt.Println("Wrong size")
return
}
// CHECK THE VALIDITY OF THE OP
op, ops := args[0], strings.Fields(validOps)
var ok bool
for _, o := range ops {
if strings.ToLower(o) == op {
ok = true
break
}
}
if !ok {
fmt.Println(invalidOpMsg)
return
}
// PRINT THE TABLE
// HEADER
fmt.Printf("%5s", op)
for i := 0; i <= size; i++ {
fmt.Printf("%5d", i)
}
fmt.Println()
// CELLS
for i := 0; i <= size; i++ {
fmt.Printf("%5d", i)
for j := 0; j <= size; j++ {
var res int
switch op {
default:
fallthrough // default is multiplication
case "*", "mul":
res = i * j
case "+", "add":
res = i + j
case "-", "sub":
res = i - j
case "%", "mod":
if j == 0 {
// continue // will continue the loop
break // breaks the switch
}
res = i % j
}
// break // breaks the loop
fmt.Printf("%5d", res)
}
fmt.Println()
}
}
================================================
FILE: x-tba/foundations/03-if-switch-loop/04-lucky-number-if-for-switch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
const (
maxTurns = 5 // less is more difficult
usage = `Welcome to the Lucky Number Game! 🍀
The program will pick %d random numbers.
Your mission is to guess one of those numbers.
The greater your number is, harder it gets.
Wanna play?
(Provide -v flag to see the picked numbers.)
`
)
func main() {
rand.Seed(time.Now().UnixNano())
args := os.Args[1:]
if len(args) != 1 {
fmt.Printf(usage, maxTurns)
return
}
var verbose bool
if args[0] == "-v" {
verbose = true
}
guess, err := strconv.Atoi(args[len(args)-1])
if err != nil {
fmt.Println("Not a number.")
return
}
if guess < 0 {
fmt.Println("Please pick a positive number.")
return
}
for turn := 0; turn < maxTurns; turn++ {
n := rand.Intn(guess + 1)
if verbose {
fmt.Printf("%d ", n)
}
if n == guess {
switch rand.Intn(3) {
case 0:
fmt.Println("🎉 YOU WIN!")
case 1:
fmt.Println("🎉 YOU'RE AWESOME!")
case 2:
fmt.Println("🎉 PERFECT!")
}
return
}
}
// msg, n := "%s Try again?\n", rand.Intn(5)
// if msg, n := "%s Try again?\n", rand.Intn(5); n <= 2 {
// fmt.Printf(msg, "☠️ YOU LOST...")
// } else if n < 3 {
// fmt.Printf(msg, "☠️ JUST A BAD LUCK...")
// } else if n == 4 {
// fmt.Printf(msg, "☠️ TRY NEXT TIME...")
// }
// var msg string
// switch rand.Intn(10) {
// // more probability
// case 0, 1, 2, 3, 4, 5:
// msg = "☠️ YOU LOST..."
// case 6, 7, 8:
// msg = "☠️ JUST A BAD LUCK..."
// default:
// msg = "☠️ TRY NEXT TIME..."
// }
// fmt.Printf("%s Try again?\n", msg)
var msg string
switch n := rand.Intn(10); {
// more probability
case n <= 5:
msg = "☠️ YOU LOST..."
case n <= 8:
msg = "☠️ JUST A BAD LUCK..."
default:
msg = "☠️ TRY NEXT TIME..."
}
fmt.Printf("%s Try again?\n", msg)
}
================================================
FILE: x-tba/foundations/03-if-switch-loop/05-path-searcher-for-range/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
)
func main() {
// Get and split the PATH environment variable
// SplitList function automatically finds the
// separator for the path env variable
words := filepath.SplitList(os.Getenv("PATH"))
// Alternative way, but above one is better:
// words := strings.Split(
// os.Getenv("PATH"),
// string(os.PathListSeparator))
query := os.Args[1:]
for _, q := range query {
for i, w := range words {
q, w = strings.ToLower(q), strings.ToLower(w)
if !strings.Contains(w, q) {
continue
}
fmt.Printf("#%-2d: %q\n", i+1, w)
}
}
}
================================================
FILE: x-tba/foundations/area-of-a-circle/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
)
func main() {
var (
radius = 10.
area float64
)
area = math.Pi * radius * radius
fmt.Printf("radius: %g -> area: %.2f\n",
radius, area)
// ALTERNATIVE:
// math.Pow calculates the power of a float number
// area = math.Pi * math.Pow(radius, 2)
}
================================================
FILE: x-tba/foundations/calc/01-shortdecl-int-conv/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// 1.
// var a int
// var b int
// 2.
// var (
// a int
// b int
// )
// 3.
// var a, b int
// 1.
// fmt.Println(a, "+", b, "=", a+b)
// 2.
// fmt.Printf("%v + %v = %v\n", a, b, a+b)
// ----
// lesson: multi-return funcs, %v, and _
a, _ := strconv.Atoi(os.Args[1])
b, _ := strconv.Atoi(os.Args[2])
fmt.Printf("%v + %v = %v\n", a, b, a+b)
}
================================================
FILE: x-tba/foundations/calc/02-if/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// lesson: if
if len(os.Args) != 3 {
fmt.Println("Usage: calc ")
return
}
a, _ := strconv.Atoi(os.Args[1])
b, _ := strconv.Atoi(os.Args[2])
fmt.Printf("%v + %v = %v\n", a, b, a+b)
}
================================================
FILE: x-tba/foundations/calc/03-floats-conv/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// lesson: len(), floats encompass integers too
if len(os.Args) != 3 {
fmt.Println("Usage: calc ")
return
}
a, _ := strconv.ParseFloat(os.Args[1], 64)
b, _ := strconv.ParseFloat(os.Args[2], 64)
fmt.Printf("%v + %v = %v\n", a, b, a+b)
}
================================================
FILE: x-tba/foundations/calc/04-error-handling/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// lesson: error handling + short decl. assignment
if len(os.Args) != 3 {
fmt.Println("Usage: calc ")
return
}
a, err := strconv.ParseFloat(os.Args[1], 64)
if err != nil {
fmt.Println("Please provide a valid number")
return
}
b, err := strconv.ParseFloat(os.Args[2], 64)
if err != nil {
fmt.Println("Please provide a valid number")
return
}
// err1 := ...
// err2 := ...
// if err1 != nil || err2 != nil {
// fmt.Println("Please provide a valid number")
// return
// }
fmt.Printf("%v + %v = %v\n", a, b, a+b)
}
================================================
FILE: x-tba/foundations/calc/05-switch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// lesson: switch
if len(os.Args) != 4 {
fmt.Println("Usage: calc ")
return
}
a, err := strconv.ParseFloat(os.Args[1], 64)
if err != nil {
fmt.Println("Please provide a valid number")
return
}
b, err := strconv.ParseFloat(os.Args[3], 64)
if err != nil {
fmt.Println("Please provide a valid number")
return
}
// multiple declare
var (
// declare & assign
op = os.Args[2]
res float64
)
switch op {
case "+":
res = a + b
case "-":
res = a - b
case "*":
res = a * b
case "/":
res = a / b
}
fmt.Printf("%v %v %v = %v\n", a, op, b, res)
}
================================================
FILE: x-tba/foundations/calc/06-switch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// lesson: switch default + multiple case
if len(os.Args) != 4 {
fmt.Println("Usage: calc ")
return
}
a, err := strconv.ParseFloat(os.Args[1], 64)
if err != nil {
fmt.Println("Please provide a valid number")
return
}
b, err := strconv.ParseFloat(os.Args[3], 64)
if err != nil {
fmt.Println("Please provide a valid number")
return
}
var (
op = os.Args[2]
res float64
)
switch op {
case "+", "plus":
op, res = "+", a+b
case "-", "minus":
op, res = "-", a-b
case "*", "times":
op, res = "*", a*b
case "/", "div":
op, res = "/", a/b
default:
fmt.Println("Please provide a valid operation.")
return
}
fmt.Printf("%v %v %v = %v\n", a, op, b, res)
}
================================================
FILE: x-tba/foundations/calc/07/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
// lesson: modulo operator and type conversion
if len(os.Args) != 4 {
fmt.Println("Usage: calc ")
return
}
a, err := strconv.ParseFloat(os.Args[1], 64)
if err != nil {
fmt.Println("Please provide a valid number")
return
}
b, err := strconv.ParseFloat(os.Args[3], 64)
if err != nil {
fmt.Println("Please provide a valid number")
return
}
var (
op = os.Args[2]
res float64
)
switch op {
case "+", "plus":
op, res = "+", a+b
case "-", "minus":
op, res = "-", a-b
case "*", "times":
op, res = "*", a*b
case "/", "div":
op, res = "/", a/b
case "%", "mod":
res = float64(int(a) % int(b))
default:
fmt.Println("Please provide a valid operation.")
return
}
fmt.Printf("%v %v %v = %v\n", a, op, b, res)
}
================================================
FILE: x-tba/foundations/calc/08-funcs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"errors"
"fmt"
"os"
"strconv"
)
func main() {
// lesson: many - split this
if len(os.Args) != 4 {
fmt.Println("Usage: calc ")
return
}
var (
a, b float64
err error
)
if a, err = parse(os.Args[1]); err != nil {
fmt.Println(err)
return
}
if b, err = parse(os.Args[3]); err != nil {
fmt.Println(err)
return
}
op := os.Args[2]
res, err := calc(a, b, op)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%v %s %v = %v\n", a, op, b, res)
}
func parse(snum string) (n float64, err error) {
n, err = strconv.ParseFloat(snum, 64)
if err != nil {
err = errors.New("Please provide a valid number")
}
return
}
func calc(a, b float64, op string) (res float64, err error) {
switch op {
case "+", "plus":
op, res = "+", a+b
case "-", "minus":
op, res = "-", a-b
case "*", "times":
op, res = "*", a*b
case "/", "div":
op, res = "/", a/b
case "%", "mod":
res = float64(int(a) % int(b))
default:
return 0, errors.New("Wrong operation: '" + op + "'")
}
return
}
================================================
FILE: x-tba/foundations/calc/09-packages/calc/calc.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package calc
import (
"errors"
"strconv"
)
// Parse ...
func Parse(snum string) (n float64, err error) {
n, err = strconv.ParseFloat(snum, 64)
if err != nil {
// Don't loose the actual error for debugging
err = errors.New("Please provide a valid number: " +
err.Error())
}
return
}
// Do ...
func Do(a, b float64, op string) (res float64, err error) {
switch op {
case "+", "plus":
op, res = "+", a+b
case "-", "minus":
op, res = "-", a-b
case "*", "times":
op, res = "*", a*b
case "/", "div":
op, res = "/", a/b
case "%", "mod":
res = float64(int(a) % int(b))
default:
return 0, errors.New("Wrong operation: '" + op + "'")
}
return
}
================================================
FILE: x-tba/foundations/calc/09-packages/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"github.com/inancgumus/learngo/x-tba/foundations/calc/09-packages/calc"
)
func main() {
// lesson: packaging
// separate dependencies like getting and validating
// user data as in here.
//
// we only put calc to another packages, not the other
// stuff.
//
// so, we can reuse the same calc package and use it
// over a web api if we want.
if len(os.Args) != 4 {
fmt.Println("Usage: calc ")
return
}
var (
a, b float64
err error
)
if a, err = calc.Parse(os.Args[1]); err != nil {
fmt.Println(err)
return
}
if b, err = calc.Parse(os.Args[3]); err != nil {
fmt.Println(err)
return
}
op := os.Args[2]
res, err := calc.Do(a, b, op)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%v %s %v = %v\n", a, op, b, res)
}
================================================
FILE: x-tba/foundations/calc/calc-scanner/calculations.txt
================================================
4 + 5
6.5 + 2
5 - 3
q
================================================
FILE: x-tba/foundations/calc/calc-scanner/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
/*
go run main.go < ./calculations.txt
If you're not on Linux or OS X, etc but on Windows,
Then, use Windows PowerShell to do the same thing.
*/
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
// After functions, you'll see that how we're going to refactor this
// into a more readable version.
func main() {
const (
promptChar = "> "
errWrongOp = "%s operation is not supported\n"
errWrongFormat = "operation is not recognized\n"
usage = `
usage: number operation number
quit : type q to quit
examples:
3 + 5
5 - 3
`
)
fmt.Println(strings.TrimSpace(usage))
for s := bufio.NewScanner(os.Stdin); ; {
var (
a, b, res float64
op string
)
fmt.Print(promptChar, " ")
if !s.Scan() {
break
}
_, err := fmt.Sscanf(s.Text(), "%f %s %f", &a, &op, &b)
if err != nil {
fmt.Fprintf(os.Stderr, errWrongFormat)
continue
}
switch op {
case "+":
res = a + b
case "-":
res = a - b
default:
fmt.Printf(errWrongOp, op)
continue
}
fmt.Printf("%g %s %g = %g\n", a, op, b, res)
}
fmt.Println("bye.")
}
================================================
FILE: x-tba/foundations/cels-to-fahr/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
func main() {
celsius := 35.
// Wrong formula : 9*celsius + 160 / 5
// Correct formula: (9*celsius + 160) / 5
fahrenheit := (9*celsius + 160) / 5
fmt.Printf("%g ºC is %g ºF\n", celsius, fahrenheit)
}
================================================
FILE: x-tba/foundations/counter/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"strconv"
)
func main() {
// var counter int
// var factor float64
var (
counter int
factor float64
)
// counter = counter + 1
counter++
fmt.Println(counter)
// counter = counter - 1
counter--
fmt.Println(counter)
// counter = counter + 5
counter += 5
fmt.Println(counter)
// counter = counter * 10
counter *= 10
fmt.Println(counter)
// counter = counter / 2.0
counter /= 2.0
fmt.Println(counter)
factor += float64(counter)
fmt.Println(counter)
var bigCounter int64
counter += int(bigCounter)
fmt.Println(counter)
fmt.Println(
"hello" + ", " + "how" + " " + "are" + " " + "today?",
)
// you can combine raw string and string literals
fmt.Println(
`hello` + `, ` + `how` + ` ` + `are` + ` ` + "today?",
)
// ------------------------------------------
// Converting non-string values into string
// ------------------------------------------
eq := "1 + 2 = "
sum := 1 + 2
// invalid op
// string concat op can only be used with strings
// fmt.Println(eq + sum)
// you need to convert it using strconv.Itoa
// Itoa = Integer to ASCII
fmt.Println(eq + strconv.Itoa(sum))
}
================================================
FILE: x-tba/foundations/feet-to-meters/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
c, _ := strconv.ParseFloat(os.Args[1], 64)
f := c*1.8 + 32
// Like this:
fmt.Printf("%g ºC is %g ºF\n", c, f)
// Or just like this (both are correct):
fmt.Printf("%g ºF\n", f)
}
================================================
FILE: x-tba/foundations/lookup/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"net"
"os"
"strings"
)
const (
missingHost = "Please provide at least one domain. --help for more information."
help = `
Host to IP Lookup:
------------------
It finds the ip addresses of the given hosts. You can provide hosts by separating them with spaces.
Example:
host google.com
host google.com uber.com`
)
func main() {
// url := "google.com"
var message string
args := os.Args
switch l := len(args); {
// case len(args) == 1:
case l == 1:
message = missingHost
case l == 2 && args[1] == "--help":
message = strings.TrimSpace(help)
}
if message != "" {
fmt.Println(message)
return
}
// for i := 0; i < len(args); i++ {}
// for i, url := range args {
for _, url := range args[1:] {
// if i == 0 {
// continue
// }
ips, err := net.LookupIP(url)
if err != nil {
fmt.Printf("%-20s => %s\n", url, err)
// break
continue
}
for _, ip := range ips {
if ip = ip.To4(); ip != nil {
fmt.Printf("%-20s => %s\n", url, ip)
}
}
}
}
================================================
FILE: x-tba/foundations/volume-of-a-sphere/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math"
"os"
"strconv"
)
func main() {
var radius, vol float64
radius, _ = strconv.ParseFloat(os.Args[1], 64)
vol = (4 * math.Pi * math.Pow(radius, 3)) / 3
fmt.Printf("radius: %g -> volume: %.2f\n", radius, vol)
}
================================================
FILE: x-tba/project-png-parser/png-parser-project/1-png-anatomy-format.md
================================================
# The Brief Anatomy of a PNG image
```
The first 24 bytes:
+=================================+
| PNG Header | 8 bytes | -> 89 50 4e 47 0d 0a 1a 0a
+---------------------+-----------+
| IHDR Chunk Header | |
| Chunk Length | 4 bytes | -> The length of the IHDR Chunk Data
| Chunk Type | 4 bytes | -> 49 48 44 52
+---------------------+-----------+
| IHDR Chunk Data | |
| Width | 4 bytes | -> uint32 — big endian
| Height | 4 bytes | -> uint32 — big endian
+=================================+
```
================================================
FILE: x-tba/project-png-parser/png-parser-project/2-png-anatomy-example.md
================================================
# The Brief Anatomy of a PNG image
```
The first 24 bytes:
(all numbers are uint32 big-endian)
PNG HEADER
╔════╗╔════╗╔════╗╔════╗╔════╗╔════╗╔════╗╔════╗
║ 89 ║║ 50 ║║ 4e ║║ 47 ║║ 0d ║║ 0a ║║ 1a ║║ 0a ║
╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝
0 1 2 3 4 5 6 7
CHUNK LENGTH CHUNK TYPE (IHDR)
╔════╗╔════╗╔════╗╔════╗╔════╗╔════╗╔════╗╔════╗
║ 00 ║║ 00 ║║ 00 ║║ 0d ║║ 49 ║║ 48 ║║ 44 ║║ 52 ║
╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝
8 9 10 11 12 13 14 15
WIDTH HEIGHT
╔════╗╔════╗╔════╗╔════╗╔════╗╔════╗╔════╗╔════╗
║ 00 ║║ 00 ║║ 02 ║║ 4c ║║ 00 ║║ 00 ║║ 03 ║║ 20 ║
╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝╚════╝
16 17 18 19 20 21 22 23
... rest of the bytes in the png image ...
```
================================================
FILE: x-tba/project-png-parser/png-parser-project/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bytes"
"encoding/binary"
"fmt"
"io/ioutil"
"os"
"runtime"
)
func main() {
args := os.Args[1:]
if len(args) == 0 {
fmt.Println("run with a PNG file")
return
}
// this is not the best way
// it's better only to read the first 24 bytes
// this reads the whole file into memory
img, err := ioutil.ReadFile(args[0])
if err != nil {
fmt.Println(err)
return
}
report()
img = append([]byte(nil), img[:24]...)
// img = img[:24:24] // unnecessary
report()
// s.PrintBacking = true
// s.MaxPerLine = 8
// s.MaxElements = 24
// s.PrintBytesHex = true
// s.Show("first 24 bytes", img)
var (
pngHeader = [...]byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}
ihdrChunkType = [...]byte{0x49, 0x48, 0x44, 0x52}
)
// ------------------------------------------
// Read the PNG header
// https://www.w3.org/TR/2003/REC-PNG-20031110/#5PNG-file-signature
// ------------------------------------------
lpng := len(pngHeader)
if !bytes.Equal(img[:lpng], pngHeader[:]) {
fmt.Println("missing PNG header")
return
}
// skip the png header
img = img[lpng:]
// ------------------------------------------
// Read the IHDR chunk header
// The IHDR chunk shall be the first chunk in the PNG datastream.
// https://www.w3.org/TR/2003/REC-PNG-20031110/#11IHDR
// ------------------------------------------
header := img[:8] // get the length and chunk type
// ensure that the chunk type is IHDR
if !bytes.Equal(header[4:8], ihdrChunkType[:]) {
fmt.Println("missing IHDR chunk")
return
}
// ------------------------------------------
// Read the IHDR Chunk Data
// ------------------------------------------
img = img[len(header):] // skip the IHDR chunk header data
ihdr := img[:8] // read the width&height from the ihdr chunk
// All integers that require more than one byte shall be in:
// network byte order = Big Endian
// https://www.w3.org/TR/2003/REC-PNG-20031110/#7Integers-and-byte-order
fmt.Printf("dimensions: %dx%d\n",
// read the first 4 bytes (width)
binary.BigEndian.Uint32(ihdr[:4]),
// read the next 4 bytes (height)
binary.BigEndian.Uint32(ihdr[4:8]))
}
func report() {
var m runtime.MemStats
runtime.GC()
runtime.ReadMemStats(&m)
fmt.Printf(" > Memory Usage: %v KB\n", m.Alloc/1024)
}
================================================
FILE: x-tba/slicing-allocs-gotcha/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Before running this program:
//
// RUN: `go run nums/main.go`
// It will create a 12 MB long nums.txt file.
import (
"fmt"
"io/ioutil"
"runtime"
s "github.com/inancgumus/prettyslice"
)
const (
loops = 1000
file = "nums.txt"
)
var buf []byte
func main() {
{
b, _ := ioutil.ReadFile(file)
buf = b[:1]
s.Show("sliced buf", buf)
}
report()
{
var nilBuf []byte
b, _ := ioutil.ReadFile(file)
buf = append(nilBuf, b[:1]...)
s.Show("copied buf", buf)
}
report()
}
func report() {
const KB = 1024
var m runtime.MemStats
r := func() {
runtime.ReadMemStats(&m)
fmt.Printf("%v KB\n", m.Alloc/KB)
}
fmt.Print(" > Before Garbage Collection: ")
r()
runtime.GC()
fmt.Print(" > After Garbage Colletion : ")
r()
}
func init() {
s.Width = 50
s.PrintBacking = true
s.MaxElements = 10
}
================================================
FILE: x-tba/slicing-allocs-gotcha/nums/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
const path = "nums.txt"
_ = os.Remove(path)
f, _ := os.OpenFile(path,
os.O_CREATE|os.O_WRONLY,
0644)
defer f.Close()
const size = 1000000
w := bufio.NewWriterSize(f, 1<<16)
for i := 1; i <= size; i++ {
fmt.Fprintf(w, "num: %d\n", i)
}
w.Flush()
}
================================================
FILE: x-tba/swapi-api-client/fetch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
const base = "https://swapi.co/api/"
func main() {
if len(os.Args) != 2 {
fmt.Println("Please provide a Ship ID")
return
}
url := base + "starships/" + os.Args[1]
response, err := http.Get(url)
if err != nil {
fmt.Println(err)
return
}
if code := response.StatusCode; code != http.StatusOK {
fmt.Println("Error:", http.StatusText(code))
return
}
// var r *http.Response
// _ = r
bodyBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
body := string(bodyBytes)
fmt.Println(body)
}
================================================
FILE: x-tba/swapi-api-client/film.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"context"
"encoding/json"
"fmt"
"strings"
)
// Film represents a single Star Wars film
type Film struct {
// All fields should be exported to be decoded
Title string `json:"title"`
Opening string `json:"opening_crawl"`
Starships []string `json:"starships"`
}
func (f Film) String() string {
var buf strings.Builder
fmt.Fprintln(&buf, f.Title)
fmt.Fprintln(&buf, strings.Repeat("-", len(f.Title)))
buf.WriteByte('\n')
fmt.Fprintln(&buf, f.Opening)
return buf.String()
}
// fetchFilm returns a Film resource by its id
func fetchFilm(ctx context.Context, id int) (film Film, err error) {
fmt.Println("requesting", fmt.Sprintf(swapi+"films/%d/", id))
c, err := request(ctx, fmt.Sprintf(swapi+"films/%d/", id))
if err != nil {
return film, err
}
return film, json.Unmarshal(c, &film)
}
================================================
FILE: x-tba/swapi-api-client/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"context"
"fmt"
"os"
"strconv"
"time"
)
// const
// nil, string, int, float64, bool, comparison
// variables
// multiple short variables
// assignment?
// if
// error handling
// functions
// returns
// defer
// struct
// encoding/json
// pointers
// concurrency
// select
// chan receive
// fmt
// Printf
// Sprintf
// Errorf
// net/http
// Get
// context/Context
// TODO: convert fmt calls to log
// TODO: you can make the fetcher a library and main package the user
// TODO: you can generate an html for the ship details? template pkg.
const timeout = 10 * time.Second
func main() {
args := os.Args[1:]
quit("give me a film id", len(args) != 1)
id, err := strconv.Atoi(args[0])
quit("film id is incorrrect", err)
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// TODO: print the ship details to a text file (or any io.Writer)
film, err := fetchFilm(ctx, id)
quit("Error occurred while fetching the film data", err)
fmt.Println(film)
// a channel also can be used to print as they come
ships := make([]Starship, len(film.Starships))
err = fetchStarships(ctx, film.Starships, ships)
quit("Error occurred while fetching starships", err)
fmt.Println("Ships used in the movie:")
fmt.Println("------------------------")
for _, ship := range ships {
fmt.Println(ship)
}
}
func quit(message string, cond interface{}) {
var quit bool
switch v := cond.(type) {
case error:
quit = true
message += ": " + v.Error()
case bool:
quit = v
}
if quit {
fmt.Fprintln(os.Stderr, message)
os.Exit(1)
}
}
================================================
FILE: x-tba/swapi-api-client/request.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"context"
"fmt"
"io"
"io/ioutil"
"net/http"
)
// MaxResponseSize limits the response bytes from the API
const MaxResponseSize = 2 << 16
// creating a robust http getter (lecture? :))
func request(ctx context.Context, url string) ([]byte, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req = req.WithContext(ctx)
resp, err := http.DefaultClient.Do(req)
if err != nil {
// Get the error from the context.
// It may contain more useful data.
select {
case <-ctx.Done():
err = ctx.Err()
default:
}
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("Bad Status: %d", resp.StatusCode)
}
// Prevents the api to shoot us unlimited amount of data
r := io.LimitReader(resp.Body, MaxResponseSize)
return ioutil.ReadAll(r)
}
================================================
FILE: x-tba/swapi-api-client/starship.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"context"
"encoding/json"
"fmt"
"regexp"
"strconv"
"strings"
)
// Starship represents a Star Wars space ship
type Starship struct {
// All fields should be exported to be decoded
Name string `json:"name"`
Credits json.Number `json:"cost_in_credits"`
Rating float64 `json:"hyperdrive_rating,string"`
}
func (ship Starship) String() string {
var buf strings.Builder
fmt.Fprintf(&buf, "Ship Name: %s\n", ship.Name)
fmt.Fprintf(&buf, "Price : %s\n", ship.Credits)
return buf.String()
}
// TODO: return error instead of quit()
func fetchStarships(ctx context.Context, shipUrls []string, ships []Starship) error {
ships = ships[:0]
re := regexp.MustCompile(`/([0-9]+)/$`)
for _, url := range shipUrls {
ids := re.FindAllStringSubmatch(url, -1)
if ids == nil {
continue
}
sid := ids[0][1]
id, _ := strconv.Atoi(sid)
// TODO: goroutine
ship, err := fetchStarship(ctx, id)
if err != nil {
return err
}
ships = append(ships, ship)
}
return nil
}
// fetchStarship returns Starship info by its id
func fetchStarship(ctx context.Context, id int) (ship Starship, err error) {
c, err := request(ctx, fmt.Sprintf(swapi+"starships/%d/", id))
if err != nil {
return ship, err
}
// -> If your response body is small enough,
// just read it all into memory using ioutil.ReadAll
// and use json.Unmarshal.
//
// -> Do not use json.Decoder if you are not dealing
// with JSON streaming.
return ship, json.Unmarshal(c, &ship)
}
================================================
FILE: x-tba/swapi-api-client/swapi.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
const swapi = "https://swapi.co/api/"
================================================
FILE: x-tba/tictactoe/00-print/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
func main() {
// VERSION #1: String Concat +
/*
fmt.Print("" +
" TIC~TAC~TOE\n" +
"\n" +
"/---+---+---\\\n" +
"| X | O | X |\n" +
"+---+---+---+\n" +
"| X | X | |\n" +
"+---+---+---+\n" +
"| O | O | O |\n" +
"\\---+---+---/\n")
*/
// VERSION #2: String Concat +
/*
fmt.Println("" +
" TIC~TAC~TOE\n" +
"\n" +
"/---+---+---\\\n" +
"| X | O | X |\n" +
"+---+---+---+\n" +
"| X | X | |\n" +
"+---+---+---+\n" +
"| O | O | O |\n" +
"\\---+---+---/")
*/
// VERSION #3: Raw Literals (multi line strings)
fmt.Println(`
TIC~TAC~TOE
/---+---+---\
| X | O | X |
+---+---+---+
| X | X | |
+---+---+---+
| O | O | O |
\---+---+---/`)
}
================================================
FILE: x-tba/tictactoe/01-vars/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
func main() {
/*
VERSION #1: Declare variables
Every type has a zero-value:
numeric types => 0
bool => false
string => ""
*/
// var banner string
// var board string
// var turn int
// var maxTurns int
// var won bool
/*
VERSION #2: Declare variables parallel (same as above)
turn and lastPos are int
won and wrongMove are bool
*/
// var banner, board string
// var turn, maxTurns int
// var won bool
/*
VERSION #3: Declare variables in a group and parallel (same as above)
*/
// var (
// banner, board string
// turn, maxTurns int
// won bool
// )
/*
VERSION #4: Declare variables in a group (same as above)
*/
var (
banner string // tictactoe banner
board string // tictactoe board
turn int // total valid turns played
maxTurns int // maximum number of turns
won bool // is there any winner?
progress float64 // remaining progress
)
/*
#5: Assignment
*/
banner = " TIC~TAC~TOE"
board = `
/---+---+---\
| | X | |
+---+---+---+
| | O | |
+---+---+---+
| | | |
\---+---+---/`
// maxTurns = 9
// turn = 2
// multiple assignment
maxTurns, turn = 9, 2
// cannot assign int to float
// progress = 1 - (turn / maxTurns) * 100
// convert ints to float so that the result will be float
// literals are typeless: they automatically get converted to the surrounding operands
progress = (1 - (float64(turn) / float64(maxTurns))) * 100
fmt.Println(banner)
fmt.Println(board)
fmt.Println()
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
// This is also valid: the expression is evaluated on the fly.
// fmt.Printf("Turns left : %.1f%%\n",
// (1 - (float64(turn) / float64(maxTurns))) * 100)
}
================================================
FILE: x-tba/tictactoe/02-short-decl/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
func main() {
var won bool // is there any winner?
banner := " TIC~TAC~TOE"
board := `
/---+---+---\
| | | |
+---+---+---+
| | | |
+---+---+---+
| | | |
\---+---+---/`
// short declaration (type-inference)
maxTurns, turn := 9, 0
progress := (1 - (float64(turn) / float64(maxTurns))) * 100
fmt.Println(banner)
fmt.Println(board)
fmt.Println()
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
================================================
FILE: x-tba/tictactoe/03-consts/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
func main() {
var (
won bool
turn int
)
// VERSION 1
// const banner = " TIC~TAC~TOE"
// const board = `
// /---+---+---\
// | X | O | X |
// +---+---+---+
// | X | X | |
// +---+---+---+
// | O | O | O |
// \---+---+---/`
//
// const maxTurns = 9
// VERSION 2
// Benefit of constants:
// + Resolved to literals at compile-time
// + Fast at runtime
// + Provides overwriting unlike variables
// + Typeless: Can change type
const (
banner = `
TIC~TAC~TOE
/---+---+---\
| X | O | X |
+---+---+---+
| X | X | |
+---+---+---+
| O | O | O |
\---+---+---/`
maxTurns = 9
)
// Constants have default types
// 1 => int
// 1.5 => float64
// true => bool
// "hi" => string
// 'a' => rune
// You cannot assign to constants
// banner = "TIC TAC TOE"
// maxTurns = 10
// no need: float64(maxTurns) — constants are typeless (like basic literals)
// if maxTurns was `const maxTurns int`; then it'd be needed.
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Println(banner)
// fmt.Println(board)
fmt.Println()
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
================================================
FILE: x-tba/tictactoe/04-funcs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const (
banner = `
TIC~TAC~TOE
/---+---+---\
| X | O | X |
+---+---+---+
| X | X | |
+---+---+---+
| O | O | O |
\---+---+---/`
maxTurns = 9
)
var (
won bool
turn int
)
func main() {
// you need to call the other functions but the main
printBoard()
printStatus()
}
// printBoard cannot use the banner
func printBoard() {
// it can only use the package-level names (identifiers)
fmt.Println(banner)
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
================================================
FILE: x-tba/tictactoe/05-testing/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
// let the printBoard function print an output
printBoard()
// the output should exactly match the following (after Output:)
// Output:
// TIC~TAC~TOE
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/05-testing/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const (
banner = `
TIC~TAC~TOE
/---+---+---\
| | | |
+---+---+---+
| | | |
+---+---+---+
| | | |
\---+---+---/`
maxTurns = 9
)
var (
won bool
turn int
)
func main() {
// you need to call the other functions but the main
printBoard()
printStatus()
}
// printBoard cannot use the banner
func printBoard() {
// it can only use the package-level names (identifiers)
fmt.Println(banner)
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
================================================
FILE: x-tba/tictactoe/06-if-switch/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
// let the printBoard function print an output
printBoard()
// the output should exactly match the following (after Output:)
// Output:
// TIC~TAC~TOE
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/06-if-switch/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const (
banner = `
TIC~TAC~TOE
/---+---+---\
| | | |
+---+---+---+
| | | |
+---+---+---+
| | | |
\---+---+---/`
maxTurns = 9
)
var (
won bool
turn int
)
func main() {
// you need to call the other functions but the main
printBoard()
printStatus()
printEnding()
}
// printBoard cannot use the banner
func printBoard() {
// it can only use the package-level names (identifiers)
fmt.Println(banner)
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
fmt.Println()
// creates a new variable that belongs to printEnding()
// current player
player := "X"
// accesses to the package-level vars: won, turn
// won = true
// turn = maxTurns
// if won {
// fmt.Printf(">>> WINNER: %s\n", player)
// } else if turn == maxTurns { // != >= <= < >
// fmt.Println(">>> TIE!")
// } else {
// fmt.Println(">> NEXT TURN!")
// }
switch {
case won:
// player := "X"
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
default:
fmt.Println(">> NEXT TURN!", player)
}
// invalid if the player is within the scope of the switch:
// fmt.Println(">> Current Player: ", player)
}
================================================
FILE: x-tba/tictactoe/07-loop/board.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// printBoard prints the board
func printBoard() {
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | O | X |
// +---+---+---+
// | O | X | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
const cellsPerLine = 3
// Prevents the Println '\n' warning
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i := 0; i < maxTurns; i++ {
lineStarts := i%cellsPerLine == 0
lineEnds := (i+1)%cellsPerLine == 0
lastLine := (i + 1) == maxTurns
if lineStarts {
fmt.Print(sepCell)
}
switchPlayer()
fmt.Printf(" %s ", player)
if lineEnds {
fmt.Println(sepCell)
}
if lineEnds && !lastLine {
fmt.Println(sepLine)
}
if lineEnds {
continue // prevents printing the sepCell below
}
// print the cell separator until 3 cells per line
fmt.Print(sepCell)
}
fmt.Printf("%s\n", sepFooter)
}
================================================
FILE: x-tba/tictactoe/07-loop/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
// let the printBoard function print an output
printBoard()
// the output should exactly match the following (after Output:)
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | O | X |
// +---+---+---+
// | O | X | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/07-loop/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool
turn int
player string // current player
)
func main() {
player = player1
turn = maxTurns
// you need to call the other functions but the main
printBoard()
printStatus()
printEnding()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
fmt.Println()
switch {
case won:
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
default:
fmt.Println(">> NEXT TURN!", player)
}
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}
================================================
FILE: x-tba/tictactoe/07-loop/skin.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
/*
Try it with this instead :)
sepHeader = "╔═══╦═══╦═══╗"
sepLine = "╠═══╬═══╬═══╣"
sepFooter = "╚═══╩═══╩═══╝"
sepCell = "║"
*/
)
================================================
FILE: x-tba/tictactoe/08-multi-loop/board.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// printBoard prints the board
func printBoard() {
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | O | X |
// +---+---+---+
// | O | X | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < maxTurns; i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
switchPlayer()
fmt.Printf(" %s %s", player, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != maxTurns {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}
================================================
FILE: x-tba/tictactoe/08-multi-loop/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
// let the printBoard function print an output
printBoard()
// the output should exactly match the following (after Output:)
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | O | X |
// +---+---+---+
// | O | X | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/08-multi-loop/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool
turn int
player string // current player
)
func main() {
player = player1
turn = maxTurns
// you need to call the other functions but the main
printBoard()
printStatus()
printEnding()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
fmt.Println()
switch {
case won:
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
default:
switchPlayer()
fmt.Println(">> NEXT TURN!", player)
}
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}
================================================
FILE: x-tba/tictactoe/08-multi-loop/skin.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)
================================================
FILE: x-tba/tictactoe/09-slices/board.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}
================================================
FILE: x-tba/tictactoe/09-slices/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
initCells()
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
initCells()
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/09-slices/init.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// initCells initialize the played cells to empty
func initCells() {
// // create a string with empty cells
// // " , , , , , , , , ,"
// var s string
// // number of cells = maxTurns
// for i := 1; i <= maxTurns; i++ {
// s += emptyCell // add an empty move
// s += "," // separate the cells with a comma
// }
// // strings are immutable — you should create a new one
// // fortunately: most of this happens in the stack memory
// // " , , , , , , , , ," -> // " , , , , , , , , "
// s = strings.TrimSuffix(s, ",")
// // store the cells in a slice (slice = list, array in other langs)
// // Split() returns a list of strings: []string (a string slice)
// // [" ", " ", " ", " ", " ", " ", " ", " ", " " ]
// cells = strings.Split(s, ",")
// Right way:
// cells = []string{" ", " ", " ", " ", " ", " ", " ", " ", " "}
//
// Or:
cells = make([]string, maxTurns)
for i := range cells {
cells[i] = emptyCell
}
}
================================================
FILE: x-tba/tictactoe/09-slices/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool // is there any winner?
turn int // total valid turns played
player string // current player
cells []string // used to draw the board: contains the players' moves
)
func main() {
player = player1
initCells()
play()
printBoard()
printStatus()
printEnding()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
fmt.Println()
switch {
case won:
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
default:
switchPlayer()
fmt.Println(">> NEXT TURN!", player)
}
}
================================================
FILE: x-tba/tictactoe/09-slices/play.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// [" ", " ", " ", " ", " ", " ", " ", " ", " " ] -> cells slice
// 0 1 2 3 4 5 6 7 8 -> indexes
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
// current player plays to the 4th position (index)
// play to a fixed position "for now".
pos := 4
// register the move: put the player's sign on the board
cells[pos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}
================================================
FILE: x-tba/tictactoe/09-slices/skin.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)
================================================
FILE: x-tba/tictactoe/10-arrays/board.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}
================================================
FILE: x-tba/tictactoe/10-arrays/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
initCells()
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
initCells()
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/10-arrays/init.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}
================================================
FILE: x-tba/tictactoe/10-arrays/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool // is there any winner?
turn int // total valid turns played
player string // current player
cells [maxTurns]string // used to draw the board: contains the players' moves
)
func main() {
player = player1
initCells()
play()
printBoard()
printStatus()
printEnding()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
fmt.Println()
switch {
case won:
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
default:
switchPlayer()
fmt.Println(">> NEXT TURN!", player)
}
}
================================================
FILE: x-tba/tictactoe/10-arrays/play.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// [" ", " ", " ", " ", " ", " ", " ", " ", " " ] -> cells slice
// 0 1 2 3 4 5 6 7 8 -> indexes
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
// current player plays to the 4th position (index)
// play to a fixed position "for now".
pos := 4
// register the move: put the player's sign on the board
cells[pos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}
================================================
FILE: x-tba/tictactoe/10-arrays/skin.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)
================================================
FILE: x-tba/tictactoe/11-randomization/board.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}
================================================
FILE: x-tba/tictactoe/11-randomization/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/11-randomization/init.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"math/rand"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}
================================================
FILE: x-tba/tictactoe/11-randomization/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool // is there any winner?
turn int // total valid turns played
player string // current player
cells [maxTurns]string // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
)
func main() {
player = player1
printBoard()
for i := 0; i < 4; i++ {
wait()
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
printEnding()
}
}
func wait() {
fmt.Println()
fmt.Scanln()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
switch {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won:
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
}
}
================================================
FILE: x-tba/tictactoe/11-randomization/play.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// [" ", " ", " ", " ", " ", " ", " ", " ", " " ] -> cells slice
// 0 1 2 3 4 5 6 7 8 -> indexes
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}
================================================
FILE: x-tba/tictactoe/11-randomization/skin.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)
================================================
FILE: x-tba/tictactoe/12-infinite-loop/board.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}
================================================
FILE: x-tba/tictactoe/12-infinite-loop/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/12-infinite-loop/init.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"math/rand"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}
================================================
FILE: x-tba/tictactoe/12-infinite-loop/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool // is there any winner?
turn int // total valid turns played
player = player1 // current player
cells [maxTurns]string // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
)
func main() {
printBoard()
// alternative:
// for won || tie {}
// this a label: it can be used by break, continue and goto
theGameLoop:
// loop forever until the game ends (tie or win)
for {
wait()
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// simple statement
switch tie := turn == maxTurns; {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won, tie:
if won {
fmt.Println(">>> WINNER:", player)
} else {
fmt.Println(">>> TIE!")
}
break theGameLoop
}
}
}
func wait() {
fmt.Println()
fmt.Scanln()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
================================================
FILE: x-tba/tictactoe/12-infinite-loop/play.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// [" ", " ", " ", " ", " ", " ", " ", " ", " " ] -> cells slice
// 0 1 2 3 4 5 6 7 8 -> indexes
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}
================================================
FILE: x-tba/tictactoe/12-infinite-loop/skin.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)
================================================
FILE: x-tba/tictactoe/13-detect-winning/board.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}
================================================
FILE: x-tba/tictactoe/13-detect-winning/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/13-detect-winning/ending.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
func checkWinOrTie() {
// intentional bug: tie shouldn't happen before winning detection
if tie = turn == maxTurns; tie {
// if tie don't check for the winning
return
}
// loop over all the players
for i := 1; i <= 2; i++ {
// check for the next player
p := player2
if i == 1 {
p = player1
}
/* check horizontals */
hor := (cells[0] == p && cells[1] == p && cells[2] == p) ||
(cells[3] == p && cells[4] == p && cells[5] == p) ||
(cells[6] == p && cells[7] == p && cells[8] == p)
/* check verticals */
ver := (cells[0] == p && cells[3] == p && cells[6] == p) ||
(cells[1] == p && cells[4] == p && cells[7] == p) ||
(cells[2] == p && cells[5] == p && cells[8] == p)
/* check diagonals */
diag := (cells[0] == p && cells[4] == p && cells[8] == p) ||
(cells[2] == p && cells[4] == p && cells[6] == p)
// any winner?
if hor || ver || diag {
won = true
// this player wins
player = p
// there is a winner so don't check for tie!
return
}
}
}
================================================
FILE: x-tba/tictactoe/13-detect-winning/init.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"math/rand"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}
================================================
FILE: x-tba/tictactoe/13-detect-winning/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won, tie bool // is there any winner or a tie?
turn int // total valid turns played
player = player1 // current player
cells [maxTurns]string // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
)
//
// VERSION 2: HELPER FUNC
//
func main() {
printBoard()
wait()
for nextTurn() {
wait()
}
// loop forever until the game ends (tie or win)
// for {
// // wait()
// if !nextTurn() {
// break
// }
// }
}
func nextTurn() bool {
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// the switch below is about winning and tie conditions.
// so it is good have checkWinOrTie() as a simple statement.
// totally optional.
switch checkWinOrTie(); {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won, tie:
if won {
fmt.Println(">>> WINNER:", player)
} else {
fmt.Println(">>> TIE!")
}
return false
}
return true
}
//
// VERSION 1: LABELED BREAK
//
// func main() {
// printBoard()
// // this a label: it can be used by break, continue and goto
// theGameLoop:
// // loop forever until game ends (tie or win)
// for {
// // wait()
// play()
// printBoard()
// fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// // the switch below is about winning and tie conditions.
// // so it is good have checkWinOrTie() as a simple statement.
// // totally optional.
// switch checkWinOrTie(); {
// default:
// printStatus()
// case wrongMove:
// fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
// wrongMove = false // reset for the next turn
// case won, tie:
// if won {
// fmt.Println(">>> WINNER:", player)
// } else {
// fmt.Println(">>> TIE!")
// }
// break theGameLoop
// }
// }
// }
func wait() {
fmt.Println()
fmt.Scanln()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
================================================
FILE: x-tba/tictactoe/13-detect-winning/play.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}
================================================
FILE: x-tba/tictactoe/13-detect-winning/skin.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)
================================================
FILE: x-tba/tictactoe/14-more-tests/board.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}
================================================
FILE: x-tba/tictactoe/14-more-tests/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/14-more-tests/ending.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
func checkWinOrTie() {
// intentional bug: tie shouldn't happen before winning detection
// if tie = turn == maxTurns; tie {
// // if tie don't check for the winning
// return
// }
// loop over all the players
for i := 1; i <= 2; i++ {
// check for the next player
p := player2
if i == 1 {
p = player1
}
/* check horizontals */
hor := (cells[0] == p && cells[1] == p && cells[2] == p) ||
(cells[3] == p && cells[4] == p && cells[5] == p) ||
(cells[6] == p && cells[7] == p && cells[8] == p)
/* check verticals */
ver := (cells[0] == p && cells[3] == p && cells[6] == p) ||
(cells[1] == p && cells[4] == p && cells[7] == p) ||
(cells[2] == p && cells[5] == p && cells[8] == p)
/* check diagonals */
diag := (cells[0] == p && cells[4] == p && cells[8] == p) ||
(cells[2] == p && cells[4] == p && cells[6] == p)
// any winner?
if hor || ver || diag {
won = true
// this player wins
player = p
// there is a winner so don't check for tie!
return
}
}
// check for tie
tie = turn == maxTurns
}
================================================
FILE: x-tba/tictactoe/14-more-tests/ending_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "testing"
func TestWin(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | O | O | X |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player2
cells[4] = player2
cells[5] = player1
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !won {
t.Errorf("won = %t; want true", won)
}
// TestWin was messing up with the results.
// Test ordering shouldn't be important.
initCells()
}
func TestTie(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | X | O | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player1
cells[4] = player2
cells[5] = player2
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !tie {
t.Errorf("tie = %t; want true", tie)
}
initCells()
}
================================================
FILE: x-tba/tictactoe/14-more-tests/init.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"math/rand"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}
================================================
FILE: x-tba/tictactoe/14-more-tests/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won, tie bool // is there any winner or a tie?
turn int // total valid turns played
player = player1 // current player
cells [maxTurns]string // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
)
// main is only responsible for the game loop, that's it.
func main() {
printBoard()
wait()
for nextTurn() {
wait()
}
}
// nextTurn prints the board for the next turn and checks for the winning conditions.
// if win or tie: returns false, otherwise true.
func nextTurn() bool {
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// the switch below is about winning and tie conditions.
// so it is good have checkWinOrTie() as a simple statement.
// totally optional.
switch checkWinOrTie(); {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won, tie:
if won {
fmt.Println(">>> WINNER:", player)
} else {
fmt.Println(">>> TIE!")
}
return false
}
return true
}
func wait() {
fmt.Println()
fmt.Scanln()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
================================================
FILE: x-tba/tictactoe/14-more-tests/play.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}
================================================
FILE: x-tba/tictactoe/14-more-tests/play_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "testing"
func TestWrongMove(t *testing.T) {
// /---+---+---\
// | X | X | X |
// +---+---+---+
// | X | X | X |
// +---+---+---+
// | X | X | X |
// \---+---+---/
// fill the board with artificial cells
for i := range cells {
cells[i] = player1
}
// any move beyond this point is wrong.
// reason: every cell is occupied.
if play(); !wrongMove {
t.Errorf("wrongMove = %t; want true", wrongMove)
}
initCells()
}
================================================
FILE: x-tba/tictactoe/14-more-tests/skin.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)
================================================
FILE: x-tba/tictactoe/15-os-args/board.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}
================================================
FILE: x-tba/tictactoe/15-os-args/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/15-os-args/ending.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
func checkWinOrTie() {
// intentional bug: tie shouldn't happen before winning detection
// if tie = turn == maxTurns; tie {
// // if tie don't check for the winning
// return
// }
// loop over all the players
for i := 1; i <= 2; i++ {
// check for the next player
p := player2
if i == 1 {
p = player1
}
/* check horizontals */
hor := (cells[0] == p && cells[1] == p && cells[2] == p) ||
(cells[3] == p && cells[4] == p && cells[5] == p) ||
(cells[6] == p && cells[7] == p && cells[8] == p)
/* check verticals */
ver := (cells[0] == p && cells[3] == p && cells[6] == p) ||
(cells[1] == p && cells[4] == p && cells[7] == p) ||
(cells[2] == p && cells[5] == p && cells[8] == p)
/* check diagonals */
diag := (cells[0] == p && cells[4] == p && cells[8] == p) ||
(cells[2] == p && cells[4] == p && cells[6] == p)
// any winner?
if hor || ver || diag {
won = true
// this player wins
player = p
// there is a winner so don't check for tie!
return
}
}
// check for tie
tie = turn == maxTurns
}
================================================
FILE: x-tba/tictactoe/15-os-args/ending_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "testing"
func TestWin(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | O | O | X |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player2
cells[4] = player2
cells[5] = player1
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !won {
t.Errorf("won = %t; want true", won)
}
// TestWin was messing up with the results.
// Test ordering shouldn't be important.
initCells()
}
func TestTie(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | X | O | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player1
cells[4] = player2
cells[5] = player2
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !tie {
t.Errorf("tie = %t; want true", tie)
}
initCells()
}
================================================
FILE: x-tba/tictactoe/15-os-args/init.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}
func setGameSpeed() {
// args can be used within the if block
// gs and err can be used in the else if and else branches
if args := os.Args; len(args) == 1 {
fmt.Println("Setting game speed to default.")
} else if gs, err := strconv.Atoi(args[1]); err != nil {
fmt.Println("Wrong game speed. Provide an integer.")
} else {
gameSpeed = time.Duration(gs) * time.Second
}
fmt.Printf("Game speed is %q.\n", gameSpeed)
}
================================================
FILE: x-tba/tictactoe/15-os-args/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const (
maxTurns = 9
defaultGameSpeed = time.Second * 2 // time between plays
)
var (
won, tie bool // is there any winner or a tie?
turn int // total valid turns played
cells [maxTurns]string // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
player = player1 // current player
gameSpeed = defaultGameSpeed // sets the default game speed
)
// main is only responsible for the game loop, that's it.
func main() {
setGameSpeed()
printBoard()
wait()
for nextTurn() {
wait()
}
}
func wait() {
fmt.Println()
time.Sleep(gameSpeed) // player thinks...
}
================================================
FILE: x-tba/tictactoe/15-os-args/play.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}
================================================
FILE: x-tba/tictactoe/15-os-args/play_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "testing"
func TestWrongMove(t *testing.T) {
// /---+---+---\
// | X | X | X |
// +---+---+---+
// | X | X | X |
// +---+---+---+
// | X | X | X |
// \---+---+---/
// fill the board with artificial cells
for i := range cells {
cells[i] = player1
}
// any move beyond this point is wrong.
// reason: every cell is occupied.
if play(); !wrongMove {
t.Errorf("wrongMove = %t; want true", wrongMove)
}
initCells()
}
================================================
FILE: x-tba/tictactoe/15-os-args/skin.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)
================================================
FILE: x-tba/tictactoe/15-os-args/turn.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// nextTurn prints the board for the next turn and checks for the winning conditions.
// if win or tie: returns false, otherwise true.
func nextTurn() bool {
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// the switch below is about winning and tie conditions.
// so it is good have checkWinOrTie() as a simple statement.
// totally optional.
switch checkWinOrTie(); {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won, tie:
if won {
fmt.Println(">>> WINNER:", player)
} else {
fmt.Println(">>> TIE!")
}
return false
}
return true
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
================================================
FILE: x-tba/tictactoe/16-types/board.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}
================================================
FILE: x-tba/tictactoe/16-types/board_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}
================================================
FILE: x-tba/tictactoe/16-types/ending.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
func checkWinOrTie() {
// intentional bug: tie shouldn't happen before winning detection
// if tie = turn == maxTurns; tie {
// // if tie don't check for the winning
// return
// }
// loop over all the players
for i := 1; i <= 2; i++ {
// check for the next player
p := player2
if i == 1 {
p = player1
}
/* check horizontals */
hor := (cells[0] == p && cells[1] == p && cells[2] == p) ||
(cells[3] == p && cells[4] == p && cells[5] == p) ||
(cells[6] == p && cells[7] == p && cells[8] == p)
/* check verticals */
ver := (cells[0] == p && cells[3] == p && cells[6] == p) ||
(cells[1] == p && cells[4] == p && cells[7] == p) ||
(cells[2] == p && cells[5] == p && cells[8] == p)
/* check diagonals */
diag := (cells[0] == p && cells[4] == p && cells[8] == p) ||
(cells[2] == p && cells[4] == p && cells[6] == p)
// any winner?
if hor || ver || diag {
won = true
// this player wins
player = p
// there is a winner so don't check for tie!
return
}
}
// check for tie
tie = turn == maxTurns
}
================================================
FILE: x-tba/tictactoe/16-types/ending_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "testing"
func TestWin(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | O | O | X |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player2
cells[4] = player2
cells[5] = player1
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !won {
t.Errorf("won = %t; want true", won)
}
// TestWin was messing up with the results.
// Test ordering shouldn't be important.
initCells()
}
func TestTie(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | X | O | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player1
cells[4] = player2
cells[5] = player2
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !tie {
t.Errorf("tie = %t; want true", tie)
}
initCells()
}
================================================
FILE: x-tba/tictactoe/16-types/init.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}
func setGameSpeed() {
// args can be used within the if block
// gs and err can be used in the else if and else branches
if args := os.Args; len(args) == 1 {
fmt.Println("Setting game speed to default.")
} else if gs, err := strconv.Atoi(args[1]); err != nil {
fmt.Println("Wrong game speed. Provide an integer.")
} else {
gameSpeed = time.Duration(gs) * time.Second
}
fmt.Printf("Game speed is %q.\n", gameSpeed)
}
================================================
FILE: x-tba/tictactoe/16-types/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"time"
)
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const (
maxTurns = 9
defaultGameSpeed = time.Second * 2 // time between plays
)
var (
won, tie bool // is there any winner or a tie?
turn int // total valid turns played
cells [maxTurns]cell // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
player = player1 // current player
gameSpeed = defaultGameSpeed // sets the default game speed
)
// main is only responsible for the game loop, that's it.
func main() {
setGameSpeed()
printBoard()
wait()
for nextTurn() {
wait()
}
}
func wait() {
fmt.Println()
time.Sleep(gameSpeed) // player thinks...
}
================================================
FILE: x-tba/tictactoe/16-types/play.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}
================================================
FILE: x-tba/tictactoe/16-types/play_test.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "testing"
func TestWrongMove(t *testing.T) {
// /---+---+---\
// | X | X | X |
// +---+---+---+
// | X | X | X |
// +---+---+---+
// | X | X | X |
// \---+---+---/
// fill the board with artificial cells
for i := range cells {
cells[i] = player1
}
// any move beyond this point is wrong.
// reason: every cell is occupied.
if play(); !wrongMove {
t.Errorf("wrongMove = %t; want true", wrongMove)
}
initCells()
}
================================================
FILE: x-tba/tictactoe/16-types/skin.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
// cell represents a tictactoe board cell
type cell string
// skin options :-)
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
player1, player2, emptyCell cell = "X", "O", " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)
================================================
FILE: x-tba/tictactoe/16-types/turn.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "fmt"
// nextTurn prints the board for the next turn and checks for the winning conditions.
// if win or tie: returns false, otherwise true.
func nextTurn() bool {
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// the switch below is about winning and tie conditions.
// so it is good have checkWinOrTie() as a simple statement.
// totally optional.
switch checkWinOrTie(); {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won, tie:
if won {
fmt.Println(">>> WINNER:", player)
} else {
fmt.Println(">>> TIE!")
}
return false
}
return true
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
================================================
FILE: x-tba/tictactoe-experiments/00-without-bufio/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"fmt"
"math/rand"
"strings"
"time"
rainbow "github.com/guineveresaenger/golang-rainbow"
)
const (
maxTurn = 9
// skin options :-)
empty = " "
player1 = " X "
player2 = " O "
header = "---+---+---"
footer = "---+---+---"
separator = "|"
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
)
// -------------------------------------------------
// INITIALIZE THE GAME
// -------------------------------------------------
var (
turn int
won bool
board = [][]string{
{empty, empty, empty},
{empty, empty, empty},
{empty, empty, empty},
}
player = player1
)
func main() {
rand.Seed(time.Now().UnixNano())
rainbow.Rainbow(banner, strings.Count(banner, "\n"))
for {
// -------------------------------------------------
// PRINT THE BOARD AND THE PROMPT
// -------------------------------------------------
fmt.Printf("\n %s\n", header)
for _, line := range board {
fmt.Printf(" %s\n", strings.Join(line, separator))
fmt.Printf(" %s\n", footer)
}
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
for i := 1; i <= 2; i++ {
m := player2
if i == 1 {
m = player1
}
b, mmm := board, strings.Repeat(m, 3)
/* horizontals */
hor := strings.Join(b[0], "") == mmm ||
strings.Join(b[1], "") == mmm ||
strings.Join(b[2], "") == mmm
/* verticals */
ver := b[0][0]+b[1][0]+b[2][0] == mmm ||
b[0][1]+b[1][1]+b[2][1] == mmm ||
b[0][2]+b[1][2]+b[2][2] == mmm
/* diagonals */
diag := b[0][0]+b[1][1]+b[2][2] == mmm ||
b[0][2]+b[1][1]+b[2][0] == mmm
won = hor || ver || diag
if won {
player = m
break
}
}
if won {
player = strings.TrimSpace(player)
fmt.Printf("\n>>> WINNER: %s\n", player)
break
} else if turn == maxTurn {
fmt.Printf("\n>>> TIE!\n")
break
}
// -------------------------------------------------
// PLAY
// -------------------------------------------------
pos := rand.Intn(9) + 1
fmt.Printf("\nPlayer %s plays to %d\n", player, pos)
// -------------------------------------------------
// IS IT A VALID MOVE?
// -------------------------------------------------
var row int
switch {
case pos <= 3:
row = 0
case pos <= 6:
row = 1
case pos <= 9:
row = 2
default:
fmt.Println(">>>", "wrong position!")
continue
}
col := pos - row*3 - 1
if board[row][col] != empty {
fmt.Println(">>>", "already played!")
continue
}
// -------------------------------------------------
// MARK THE MOVE AND INCREMENT THE TURN
// -------------------------------------------------
// put a mark on the board
board[row][col] = player
// switch to the next player
if player == player1 {
player = player2
} else {
player = player1
}
turn++
// time.Sleep(time.Millisecond * 100)
}
}
================================================
FILE: x-tba/tictactoe-experiments/01-without-funcs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
rainbow "github.com/guineveresaenger/golang-rainbow"
)
const (
maxTurn = 9
// skin options :-)
empty = " "
player1 = " X "
player2 = " O "
header = "---+---+---"
footer = "---+---+---"
separator = "|"
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
)
// -------------------------------------------------
// INITIALIZE THE GAME
// -------------------------------------------------
var (
turn int
won bool
board = [3][3]string{
{empty, empty, empty},
{empty, empty, empty},
{empty, empty, empty},
}
player = player1
// for saving the replay.log
inputs []byte
)
func main() {
rainbow.Rainbow(banner, strings.Count(banner, "\n"))
in := bufio.NewScanner(os.Stdin)
for {
// -------------------------------------------------
// PRINT THE BOARD AND THE PROMPT
// -------------------------------------------------
fmt.Printf("\n %s\n", header)
for _, line := range board {
fmt.Printf(" %s\n", strings.Join(line[:], separator))
fmt.Printf(" %s\n", footer)
}
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
for _, m := range [2]string{player1, player2} {
b, mmm := board, strings.Repeat(m, 3)
won = /* horizontals */
strings.Join(b[0][:], "") == mmm ||
strings.Join(b[1][:], "") == mmm ||
strings.Join(b[2][:], "") == mmm ||
/* verticals */
b[0][0]+b[1][0]+b[2][0] == mmm ||
b[0][1]+b[1][1]+b[2][1] == mmm ||
b[0][2]+b[1][2]+b[2][2] == mmm ||
/* diagonals */
b[0][0]+b[1][1]+b[2][2] == mmm ||
b[0][2]+b[1][1]+b[2][0] == mmm
if won {
player = m
break
}
}
if won {
player = strings.TrimSpace(player)
fmt.Printf("\n>>> WINNER: %s\n", player)
break
} else if turn++; turn == maxTurn+1 {
fmt.Printf("\n>>> TIE!\n")
break
}
// -------------------------------------------------
// CHECK THE MOVE AND PLAY
// -------------------------------------------------
// get the input
fmt.Printf("\nPLAYER: %q [1-9]: ", player)
if !in.Scan() {
break
}
// Atoi already return 0 on error; no need to check
// it for the following switch to work
pos, _ := strconv.Atoi(in.Text())
// Save the input for replaying
inputs = append(inputs, byte(pos+48), '\n')
var row int
switch {
case pos >= 1 && pos <= 3:
row = 0
case pos >= 4 && pos <= 6:
row = 1
case pos >= 7 && pos <= 9:
row = 2
default:
fmt.Println("\n>>>", "wrong position!")
continue
}
col := pos - row*3 - 1
if board[row][col] != empty {
fmt.Println("\n>>>", "already played!")
continue
}
// put a mark on the board
board[row][col] = player
// switch to the next player
if player == player1 {
player = player2
} else {
player = player1
}
}
if err := ioutil.WriteFile("replay.log", inputs, 0644); err != nil {
fmt.Fprintf(os.Stderr, "Cannot save replay: %v", err)
}
}
================================================
FILE: x-tba/tictactoe-experiments/02-with-funcs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const (
// skin options :-)
emptyMark = "☆"
mark1 = "💀"
mark2 = "🎈"
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
maxTurn = 9
)
func main() {
fmt.Println(banner)
loop(bufio.NewScanner(os.Stdin))
}
func loop(in *bufio.Scanner) {
var (
turn int
player = mark1
board = createBoard()
)
for {
prompt(board, player)
if !in.Scan() {
break
}
msg := play(board, player, getMove(in.Text()))
if msg != "" {
fmt.Println("\n>>>", msg)
continue
}
turn++
if msg := finito(board, turn, player); msg != "" {
printBoard(board, player)
fmt.Printf("\n%s\n", msg)
break
}
player = switchTo(player)
}
}
func createBoard() [][]string {
return [][]string{
{emptyMark, emptyMark, emptyMark},
{emptyMark, emptyMark, emptyMark},
{emptyMark, emptyMark, emptyMark},
}
}
func prompt(board [][]string, player string) {
printBoard(board, player)
fmt.Printf("\n%s [1-9]: ", player)
}
func printBoard(board [][]string, player string) {
fmt.Println()
fmt.Println("---+----+---")
for _, line := range board {
fmt.Printf("%s\n", strings.Join(line, " | "))
fmt.Println("---+----+---")
}
}
func getMove(move string) int {
// Atoi already return 0 on error; no need to check
// it for the following switch to work
pos, _ := strconv.Atoi(move)
return pos
}
func play(board [][]string, player string, pos int) string {
var row int
switch {
case pos >= 7 && pos <= 9:
row = 2
case pos >= 4 && pos <= 6:
row = 1
case pos >= 1 && pos <= 3:
row = 0
default:
return "wrong position"
}
col := pos - row*3 - 1
if board[row][col] != emptyMark {
return "already played!"
}
// put the player
board[row][col] = player
return ""
}
func finito(board [][]string, turn int, player string) string {
switch {
case won(board):
return fmt.Sprintf("WINNER: %s", player)
case turn == maxTurn:
return "TIE!"
}
return ""
}
func won(board [][]string) (won bool) {
for _, m := range [2]string{mark1, mark2} {
b, mmm := board, strings.Repeat(m, 3)
won = /* horizontals */
strings.Join(b[0], "") == mmm ||
strings.Join(b[1], "") == mmm ||
strings.Join(b[2], "") == mmm ||
/* verticals */
b[0][0]+b[1][0]+b[2][0] == mmm ||
b[0][1]+b[1][1]+b[2][1] == mmm ||
b[0][2]+b[1][2]+b[2][2] == mmm ||
/* diagonals */
b[0][0]+b[1][1]+b[2][2] == mmm ||
b[0][2]+b[1][1]+b[2][0] == mmm
if won {
return true
}
}
return false
}
func switchTo(player string) string {
if player == mark1 {
return mark2
}
return mark1
}
================================================
FILE: x-tba/tictactoe-experiments/03-with-structs/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const (
// skin options :-)
emptyMark = "☆"
mark1 = "💀"
mark2 = "🎈"
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
maxTurn = 9
)
type game struct {
board [][]string
turn int
player string
}
func main() {
fmt.Println(banner)
loop(bufio.NewScanner(os.Stdin))
}
func loop(in *bufio.Scanner) {
g := game{
player: mark1,
board: createBoard(),
}
for {
prompt(g)
if !in.Scan() {
break
}
msg := play(g, getMove(in.Text()))
if msg != "" {
fmt.Println("\n>>>", msg)
continue
}
g.turn++
if msg := finito(g); msg != "" {
printBoard(g.board)
fmt.Printf("\n%s\n", msg)
break
}
g.player = switchTo(g.player)
}
}
func createBoard() [][]string {
return [][]string{
{emptyMark, emptyMark, emptyMark},
{emptyMark, emptyMark, emptyMark},
{emptyMark, emptyMark, emptyMark},
}
}
func prompt(g game) {
printBoard(g.board)
fmt.Printf("\n%s [1-9]: ", g.player)
}
func printBoard(board [][]string) {
fmt.Println()
fmt.Println("---+----+---")
for _, line := range board {
fmt.Printf("%s\n", strings.Join(line, " | "))
fmt.Println("---+----+---")
}
}
func getMove(move string) int {
// Atoi already return 0 on error; no need to check
// it for the following switch to work
pos, _ := strconv.Atoi(move)
return pos
}
// NOTE: manipulates the game object
func play(g game, pos int) string {
var row int
switch {
case pos >= 7 && pos <= 9:
row = 2
case pos >= 4 && pos <= 6:
row = 1
case pos >= 1 && pos <= 3:
row = 0
default:
return "wrong position"
}
col := pos - row*3 - 1
if g.board[row][col] != emptyMark {
return "already played!"
}
// put the player
g.board[row][col] = g.player
return ""
}
func finito(g game) string {
switch {
case won(g.board):
return fmt.Sprintf("WINNER: %s", g.player)
case g.turn == maxTurn:
return "TIE!"
}
return ""
}
func won(board [][]string) (won bool) {
for _, m := range [2]string{mark1, mark2} {
b, mmm := board, strings.Repeat(m, 3)
won = /* horizontals */
strings.Join(b[0], "") == mmm ||
strings.Join(b[1], "") == mmm ||
strings.Join(b[2], "") == mmm ||
/* verticals */
b[0][0]+b[1][0]+b[2][0] == mmm ||
b[0][1]+b[1][1]+b[2][1] == mmm ||
b[0][2]+b[1][2]+b[2][2] == mmm ||
/* diagonals */
b[0][0]+b[1][1]+b[2][2] == mmm ||
b[0][2]+b[1][1]+b[2][0] == mmm
if won {
return true
}
}
return false
}
func switchTo(player string) string {
if player == mark1 {
return mark2
}
return mark1
}
================================================
FILE: x-tba/tictactoe-experiments/04-with-methods/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const (
// skin options :-)
emptyMark = "☆"
mark1 = "💀"
mark2 = "🎈"
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
maxTurn = 9
)
func main() {
fmt.Println(banner)
loop(bufio.NewScanner(os.Stdin))
}
type game struct {
board [][]string
turn int
player string
}
func loop(in *bufio.Scanner) {
g := newGame()
for {
g.prompt()
if !in.Scan() {
break
}
// Atoi already return 0 on error; no need to check
// it for the following switch to work
pos, _ := strconv.Atoi(in.Text())
msg := g.play(pos)
if msg != "" {
fmt.Println("\n>>>", msg)
continue
}
g.turn++
if msg := g.finito(); msg != "" {
g.print()
fmt.Printf("\n%s\n", msg)
break
}
g.player = switchTo(g.player)
}
}
func newGame() game {
return game{
player: mark1,
board: [][]string{
{emptyMark, emptyMark, emptyMark},
{emptyMark, emptyMark, emptyMark},
{emptyMark, emptyMark, emptyMark},
},
}
}
func (g game) prompt() {
g.print()
fmt.Printf("\n%s [1-9]: ", g.player)
}
func (g game) print() {
fmt.Println()
fmt.Println("---+----+---")
for _, line := range g.board {
fmt.Printf("%s\n", strings.Join(line, " | "))
fmt.Println("---+----+---")
}
}
func (g game) play(pos int) string {
var row int
switch {
case pos >= 7 && pos <= 9:
row = 2
case pos >= 4 && pos <= 6:
row = 1
case pos >= 1 && pos <= 3:
row = 0
default:
return "wrong position"
}
col := pos - row*3 - 1
if g.board[row][col] != emptyMark {
return "already played!"
}
// put the player
g.board[row][col] = g.player
return ""
}
func (g game) finito() string {
switch {
case g.won():
return fmt.Sprintf("WINNER: %s", g.player)
case g.turn == maxTurn:
return "TIE!"
}
return ""
}
func (g game) won() (won bool) {
for _, m := range [2]string{mark1, mark2} {
b, mmm := g.board, strings.Repeat(m, 3)
won = /* horizontals */
strings.Join(b[0], "") == mmm ||
strings.Join(b[1], "") == mmm ||
strings.Join(b[2], "") == mmm ||
/* verticals */
b[0][0]+b[1][0]+b[2][0] == mmm ||
b[0][1]+b[1][1]+b[2][1] == mmm ||
b[0][2]+b[1][2]+b[2][2] == mmm ||
/* diagonals */
b[0][0]+b[1][1]+b[2][2] == mmm ||
b[0][2]+b[1][1]+b[2][0] == mmm
if won {
return true
}
}
return false
}
func switchTo(player string) string {
if player == mark1 {
return mark2
}
return mark1
}
================================================
FILE: x-tba/tictactoe-experiments/05-with-pointers/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
fmt.Println(`
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`)
loop(bufio.NewScanner(os.Stdin))
}
const (
// skin options :-)
emptyMark = "☆"
mark1 = "💀"
mark2 = "🎈"
maxTurn = 9
)
type game struct {
board [][]string
turn int
player string
buf strings.Builder
}
func loop(in *bufio.Scanner) {
g := newGame()
for {
g.prompt()
if !in.Scan() {
break
}
// Atoi already return 0 on error; no need to check
// it for the following switch to work
pos, _ := strconv.Atoi(in.Text())
msg := g.play(pos)
if msg != "" {
fmt.Println("\n>>>", msg)
continue
}
if msg := g.finito(); msg != "" {
fmt.Printf("\n%s%s\n", g, msg)
break
}
g.next()
}
}
func newGame() *game {
return &game{
player: mark1,
board: [][]string{
{emptyMark, emptyMark, emptyMark},
{emptyMark, emptyMark, emptyMark},
{emptyMark, emptyMark, emptyMark},
},
}
}
func (g *game) prompt() {
fmt.Printf("\n%s%s [1-9]: ", g, g.player)
}
func (g *game) String() string {
g.buf.Reset()
g.buf.WriteRune('\n')
g.buf.WriteString("---+----+---\n")
for _, line := range g.board {
g.buf.WriteString(strings.Join(line, " | "))
g.buf.WriteRune('\n')
g.buf.WriteString("---+----+---\n")
}
return g.buf.String()
}
func (g *game) play(pos int) string {
var row int
switch {
case pos >= 7 && pos <= 9:
row = 2
case pos >= 4 && pos <= 6:
row = 1
case pos >= 1 && pos <= 3:
row = 0
default:
return "wrong position"
}
col := pos - row*3 - 1
if g.board[row][col] != emptyMark {
return "already played!"
}
// put the player
g.board[row][col] = g.player
return ""
}
func (g *game) finito() string {
g.turn++
switch {
case g.won():
return fmt.Sprintf("WINNER: %s", g.player)
case g.turn == maxTurn:
return "TIE!"
}
return ""
}
func (g *game) won() (won bool) {
for _, m := range [2]string{mark1, mark2} {
b, mmm := g.board, strings.Repeat(m, 3)
won = /* horizontals */
strings.Join(b[0], "") == mmm ||
strings.Join(b[1], "") == mmm ||
strings.Join(b[2], "") == mmm ||
/* verticals */
b[0][0]+b[1][0]+b[2][0] == mmm ||
b[0][1]+b[1][1]+b[2][1] == mmm ||
b[0][2]+b[1][2]+b[2][2] == mmm ||
/* diagonals */
b[0][0]+b[1][1]+b[2][2] == mmm ||
b[0][2]+b[1][1]+b[2][0] == mmm
if won {
return true
}
}
return false
}
func (g *game) next() {
if g.player == mark1 {
g.player = mark2
} else {
g.player = mark1
}
}
================================================
FILE: x-tba/tictactoe-experiments/06-refactor/game.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"strings"
)
type state int
const (
maxTurn = 9
wrongPosition = -2
statePlaying state = iota
stateWon
stateTie
stateAlreadyPlayed
stateWrongPosition
)
type game struct {
board [][]string
turn int
player string
skin // embed the skin
logger // embed the logger
}
func newGame(s skin, l logger) *game {
return &game{
player: s.mark1,
board: [][]string{
{s.empty, s.empty, s.empty},
{s.empty, s.empty, s.empty},
{s.empty, s.empty, s.empty},
},
skin: s,
logger: l,
}
}
func (g *game) play(pos int) state {
if st := g.move(pos); st != statePlaying {
return st
}
g.turn++ // increment the turn
// first check the winner then check the tie
// or the last mover won't win
switch {
case g.won():
return stateWon
case g.turn == maxTurn:
return stateTie
}
g.changePlayer()
return statePlaying
}
func (g *game) move(pos int) state {
row, col := position(pos)
if row+col == wrongPosition {
return stateWrongPosition
}
if g.board[row][col] != g.empty {
return stateAlreadyPlayed
}
// put the player's mark on the board
g.board[row][col] = g.player
return statePlaying
}
// we can detect the winning state just by comparing the strings
// because, the game board is a bunch of strings
func (g *game) won() (won bool) {
for _, m := range [2]string{g.mark1, g.mark2} {
b, mmm := g.board, strings.Repeat(m, 3)
won = /* horizontals */
strings.Join(b[0], "") == mmm ||
strings.Join(b[1], "") == mmm ||
strings.Join(b[2], "") == mmm ||
/* verticals */
b[0][0]+b[1][0]+b[2][0] == mmm ||
b[0][1]+b[1][1]+b[2][1] == mmm ||
b[0][2]+b[1][2]+b[2][2] == mmm ||
/* diagonals */
b[0][0]+b[1][1]+b[2][2] == mmm ||
b[0][2]+b[1][1]+b[2][0] == mmm
if won {
return true
}
}
return false
}
// this method should have a pointer receiver
// because, it changes the game value
func (g *game) changePlayer() {
if g.player == g.mark1 {
g.player = g.mark2
} else {
g.player = g.mark1
}
}
func (g *game) print() {
g.Println()
g.Println(g.header)
for i, line := range g.board {
g.Print(g.separator)
for _, m := range line {
g.Printf("%2s%s", m, g.separator)
}
if i+1 != len(g.board) {
g.Printf("\n%s\n", g.middle)
}
}
g.Printf("\n%s\n", g.footer)
}
// this function doesn't depend on the game state
// so, make it a function instead of a method
func position(pos int) (row, col int) {
switch {
case pos >= 1 && pos <= 3:
row = 0
case pos >= 4 && pos <= 6:
row = 1
case pos >= 7 && pos <= 9:
row = 2
default:
return -1, -1
}
return row, pos - row*3 - 1
}
================================================
FILE: x-tba/tictactoe-experiments/06-refactor/logger.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
type logger struct {
print func(...interface{}) (int, error)
printf func(fmt string, args ...interface{}) (int, error)
println func(...interface{}) (int, error)
}
func (l logger) Print(args ...interface{}) {
l.print(args...)
}
func (l logger) Printf(fmt string, args ...interface{}) {
l.printf(fmt, args...)
}
func (l logger) Println(args ...interface{}) {
l.println(args...)
}
================================================
FILE: x-tba/tictactoe-experiments/06-refactor/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"bufio"
"fmt"
"os"
"strconv"
c "github.com/fatih/color"
rainbow "github.com/guineveresaenger/golang-rainbow"
)
// TODO: move the main logic into a helper
func main() {
const banner = `
~~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~~`
in := bufio.NewScanner(os.Stdin)
sk := selectSkin(in)
lg := logger{
print: fmt.Print,
printf: fmt.Printf,
println: fmt.Println,
}
for {
g := newGame(sk, lg)
game:
for {
rainbow.Rainbow(banner, 3)
g.print()
fmt.Printf(c.CyanString("\n%s [1-9]: ", g.player))
if !in.Scan() {
break
}
pos, _ := strconv.Atoi(in.Text())
switch st := g.play(pos); st {
case stateAlreadyPlayed, stateWrongPosition:
announce(g, st)
continue
case stateWon, stateTie:
announce(g, st)
break game
}
g.Print("\033[2J")
}
fmt.Print(c.MagentaString("One more game? [y/n]: "))
if in.Scan(); in.Text() != "y" {
fmt.Println("OK, bye!")
break
}
}
}
func announce(g *game, st state) {
red := c.New(c.FgRed, c.Bold)
green := c.New(c.BgBlack, c.FgGreen, c.Bold)
switch st {
case stateAlreadyPlayed, stateWrongPosition:
red.Printf("\n>>> You can't play there!\n")
case stateWon:
g.print()
green.Printf("\nWINNER: %s\n", g.player)
case stateTie:
g.print()
green.Printf("\nTIE!\n")
}
}
func selectSkin(in *bufio.Scanner) skin {
fmt.Println(c.MagentaString("Our finest selection of skins:"))
for name := range skins {
fmt.Printf("- %s\n", name)
}
fmt.Print(c.GreenString("\nEnter the name of the skin: "))
in.Scan()
if sk, ok := skins[in.Text()]; ok {
return sk
}
return defaultSkin
}
================================================
FILE: x-tba/tictactoe-experiments/06-refactor/resources.md
================================================
https://github.com/mattn/go-runewidth
https://github.com/olekukonko/tablewriter
https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
================================================
FILE: x-tba/tictactoe-experiments/06-refactor/skins.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "github.com/fatih/color"
// skin options :-)
type skin struct {
empty, mark1, mark2 string
header, middle, footer, separator string
unicode bool
}
var skins = map[string]skin{
"colorful": colorfulSkin,
"poseidon": poseidonSkin,
"statues": statuesSkin,
"aliens": aliensSkin,
"snow": snowSkin,
"monkeys": monkeysSkin,
}
var defaultSkin = skin{
empty: " ",
mark1: " X ",
mark2: " O ",
header: "┌───┬───┬───┐",
middle: "├───┼───┼───┤",
footer: "└───┴───┴───┘",
separator: "│",
}
var colorfulSkin = skin{
empty: " ",
mark1: color.CyanString(" X "),
mark2: color.HiMagentaString(" O "),
header: color.HiBlueString("┌───┬───┬───┐"),
middle: color.HiBlueString("├───┼───┼───┤"),
footer: color.HiBlueString("└───┴───┴───┘"),
separator: color.BlueString("│"),
}
var poseidonSkin = skin{
empty: "❓ ",
mark1: "🔱 ",
mark2: "⚓️ ",
header: "●————●————●————●",
middle: "●————●————●————●",
footer: "●————●————●————●",
separator: "⎮ ",
}
var statuesSkin = skin{
empty: "❓ ",
mark1: "🗿 ",
mark2: "🗽 ",
header: "┌────┬────┬────┐",
middle: "├────┼────┼────┤",
footer: "└────┴────┴────┘",
separator: "│ ",
}
var aliensSkin = skin{
empty: "❓ ",
mark1: "👽 ",
mark2: "👾 ",
header: "┌────┬────┬────┐",
middle: "├────┼────┼────┤",
footer: "└────┴────┴────┘",
separator: "│ ",
}
var snowSkin = skin{
empty: "❓ ",
mark1: "⛄ ️ ",
mark2: "❄️ ",
header: "╔════╦════╦════╗",
middle: "╠════╬════╬════╣",
footer: "╚════╩════╩════╝",
separator: "║ ",
}
var monkeysSkin = skin{
empty: "🍌 ",
mark1: "🙈 ",
mark2: "🙉 ",
header: "┌────┬────┬────┐",
middle: "├────┼────┼────┤",
footer: "└────┴────┴────┘",
separator: "│ ",
}
================================================
FILE: x-tba/tictactoe-experiments/README.md
================================================
**Check out:**
Tic-Tac-Toe Gist:
https://gist.github.com/agalal/bff3cb779c337274d2a3462c630f4d74
================================================
FILE: x-tba/wizards-structs/marshal/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"encoding/json"
"fmt"
)
// Wizard is one of the greatest of people
type Wizard struct {
// name won't be marshalled (should be exported)
Name string `json:"name,omitempty"`
Lastname string `json:"last_name"`
Nick string `json:"-"`
}
func main() {
wizards := []Wizard{
{Name: "Albert", Lastname: "Einstein", Nick: "emc2"},
{Name: "Isaac", Lastname: "Newton", Nick: "apple"},
{Name: "Stephen", Lastname: "Hawking", Nick: "blackhole"},
{Name: "Marie", Lastname: "Curie", Nick: "radium"},
{Name: "", Lastname: "Darwin", Nick: "fittest"},
}
bytes, err := json.MarshalIndent(wizards, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
}
================================================
FILE: x-tba/wizards-structs/server/list.tmpl.html
================================================
There are {{len .}} wizards.
{{range .}}
👉 {{.Name}} {{.Lastname}} ({{.Nick}})
{{end}}
================================================
FILE: x-tba/wizards-structs/server/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"encoding/json"
"net/http"
)
func main() {
http.HandleFunc("/add", onlyPost(add))
http.HandleFunc("/list", list)
panic(http.ListenAndServe(":8000", nil))
}
func add(w http.ResponseWriter, r *http.Request) {
var wiz wizard
if err := json.NewDecoder(r.Body).Decode(&wiz); err != nil {
panic(err)
}
db.add(wiz)
w.WriteHeader(http.StatusOK)
}
func list(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=UTF-8")
w.WriteHeader(http.StatusOK)
tmpl.Execute(w, db.list())
}
func onlyPost(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method == "POST" {
next(w, r)
return
}
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("NOT OK"))
}
}
================================================
FILE: x-tba/wizards-structs/server/store.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "sync"
type wizard struct {
Name string `json:"name"`
Lastname string `json:"last_name"`
Nick string `json:"nick"`
}
type storage struct {
sync.RWMutex
wizards []wizard
}
func (db *storage) add(w wizard) {
db.Lock()
defer db.Unlock()
db.wizards = append(db.wizards, w)
}
func (db *storage) list() []wizard {
db.RLock()
defer db.RUnlock()
return db.wizards
}
var db *storage
func init() {
db = new(storage)
}
================================================
FILE: x-tba/wizards-structs/server/templates.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import "html/template"
var tmpl *template.Template
func init() {
tmpl = template.Must(
template.New("list.tmpl").
ParseFiles("list.tmpl"))
}
================================================
FILE: x-tba/wizards-structs/unmarshal/main.go
================================================
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// For more tutorials : https://learngoprogramming.com
// In-person training : https://www.linkedin.com/in/inancgumus/
// Follow me on twitter: https://twitter.com/inancgumus
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"strings"
)
// Wizard is one of the greatest of people
type Wizard struct {
// name won't be marshalled (should be exported)
Name string `json:name`
Lastname string `json:"-"`
Nick string `json:"nick"`
}
func main() {
file, err := ioutil.ReadFile("../marshal/wizards.json")
if err != nil {
panic(err)
}
wizards := make([]Wizard, 10)
if json.Unmarshal(file, &wizards) != nil {
panic(err)
}
fmt.Printf("%-15s %-15s\n%s",
"Name", "Nick", strings.Repeat("=", 25))
for _, w := range wizards {
fmt.Printf("%-15s %-15s\n", w.Name, w.Nick)
}
}