From ccfa68200aed2e33545275dd52919016af1df6b9 Mon Sep 17 00:00:00 2001 From: Inanc Gumus Date: Sat, 17 Aug 2019 15:54:40 +0300 Subject: [PATCH] move: interfaces error handling and advanced funcs --- .../_legacy/01-variadic-funcs/main.go | 73 ---------- .../_legacy/02-func-values/main.go | 52 ------- .../_legacy/03-func-to-func/main.go | 82 ----------- .../_legacy/04-closures/main.go | 76 ----------- .../_legacy/05-higher-order-funcs/main.go | 58 -------- .../_legacy/06-functional-programming/main.go | 97 ------------- .../log-parser-exp/Makefile | 29 ---- .../log-parser-exp/field.go | 20 --- .../log-parser-exp/filters.go | 34 ----- .../log-parser-exp/groupers.go | 20 --- .../log-parser-exp/log.txt | 16 --- .../log-parser-exp/log_err_missing.txt | 16 --- .../log-parser-exp/log_err_negative.txt | 16 --- .../log-parser-exp/log_err_str.txt | 16 --- .../log-parser-exp/main.go | 59 -------- .../log-parser-exp/pipeline.go | 70 ---------- .../log-parser-exp/result.go | 36 ----- .../log-parser-exp/textreader.go | 38 ------ .../log-parser-exp/textreaderfast.go | 129 ------------------ .../log-parser-exp/textwriter.go | 43 ------ 29-interfaces/logparser-funcs/log.txt | 6 - .../logparser-funcs/log_err_missing.txt | 6 - .../logparser-funcs/log_err_negative.txt | 6 - 29-interfaces/logparser-funcs/log_err_str.txt | 6 - 29-interfaces/logparser-funcs/main.go | 26 ---- 29-interfaces/logparser-funcs/parser.go | 70 ---------- 29-interfaces/logparser-funcs/result.go | 27 ---- 29-interfaces/logparser-funcs/summarize.go | 36 ----- 29-interfaces/logparser-funcs/summary.go | 70 ---------- 29-interfaces/logparser-nopkg/log.txt | 6 - .../logparser-nopkg/log_err_missing.txt | 6 - .../logparser-nopkg/log_err_negative.txt | 6 - 29-interfaces/logparser-nopkg/log_err_str.txt | 6 - 29-interfaces/logparser-nopkg/main.go | 24 ---- 29-interfaces/logparser-nopkg/parser.go | 52 ------- 29-interfaces/logparser-nopkg/result.go | 60 -------- 29-interfaces/logparser-nopkg/summarize.go | 51 ------- 29-interfaces/logparser-nopkg/summary.go | 70 ---------- 29-interfaces/logparser-pkg/log.txt | 6 - .../logparser-pkg/log_err_missing.txt | 6 - .../logparser-pkg/log_err_negative.txt | 6 - 29-interfaces/logparser-pkg/log_err_str.txt | 6 - 29-interfaces/logparser-pkg/main.go | 26 ---- 29-interfaces/logparser-pkg/report/parser.go | 52 ------- 29-interfaces/logparser-pkg/report/result.go | 60 -------- 29-interfaces/logparser-pkg/report/summary.go | 85 ------------ 29-interfaces/logparser-pkg/summarize.go | 73 ---------- 29-interfaces/logparser-testing/log.txt | 6 - .../logparser-testing/log_err_missing.txt | 6 - .../logparser-testing/log_err_negative.txt | 6 - .../logparser-testing/log_err_str.txt | 6 - 29-interfaces/logparser-testing/main.go | 26 ---- 29-interfaces/logparser-testing/main_test.go | 59 -------- .../logparser-testing/report/parser.go | 52 ------- .../logparser-testing/report/parser_test.go | 55 -------- .../logparser-testing/report/result.go | 60 -------- .../logparser-testing/report/summary.go | 86 ------------ .../logparser-testing/report/summary_test.go | 44 ------ 29-interfaces/logparser-testing/summarize.go | 73 ---------- .../xxx-monte-carlo/main.go | 0 .../01-deferred-funcs/main.go | 0 .../02-png-detector/main.go | 0 .../02-png-detector/pngs/cups-jpg.png | Bin .../02-png-detector/pngs/empty.png | 0 .../02-png-detector/pngs/forest-jpg.png | Bin .../02-png-detector/pngs/golden.png | Bin .../02-png-detector/pngs/shakespeare-text.png | 0 .../02-png-detector/pngs/work.png | Bin .../03-png-detector-with-panic/main.go | 0 .../pngs/cups-jpg.png | Bin .../03-png-detector-with-panic/pngs/empty.png | 0 .../pngs/forest-jpg.png | Bin .../pngs/golden.png | Bin .../pngs/shakespeare-text.png | 0 .../03-png-detector-with-panic/pngs/work.png | Bin .../04-image-detector-recover/main.go | 0 .../pngs/cups-jpg.png | Bin .../04-image-detector-recover/pngs/empty.png | 0 .../pngs/forest-jpg.png | Bin .../04-image-detector-recover/pngs/golden.png | Bin .../pngs/shakespeare-text.png | 0 .../04-image-detector-recover/pngs/work.png | Bin .../04b-named-params/main.go | 0 .../04b-named-params/pngs/cups-jpg.png | Bin .../04b-named-params/pngs/empty.png | 0 .../04b-named-params/pngs/forest-jpg.png | Bin .../04b-named-params/pngs/golden.png | Bin .../pngs/shakespeare-text.png | 0 .../04b-named-params/pngs/work.png | Bin .../exercises/01-refactor/main.go | 0 .../exercises/01-refactor/solution/main.go | 0 .../exercises/README.md | 0 92 files changed, 2313 deletions(-) delete mode 100644 27-functional-programming/_legacy/01-variadic-funcs/main.go delete mode 100644 27-functional-programming/_legacy/02-func-values/main.go delete mode 100644 27-functional-programming/_legacy/03-func-to-func/main.go delete mode 100644 27-functional-programming/_legacy/04-closures/main.go delete mode 100644 27-functional-programming/_legacy/05-higher-order-funcs/main.go delete mode 100644 27-functional-programming/_legacy/06-functional-programming/main.go delete mode 100644 27-functional-programming/log-parser-exp/Makefile delete mode 100644 27-functional-programming/log-parser-exp/field.go delete mode 100644 27-functional-programming/log-parser-exp/filters.go delete mode 100644 27-functional-programming/log-parser-exp/groupers.go delete mode 100644 27-functional-programming/log-parser-exp/log.txt delete mode 100644 27-functional-programming/log-parser-exp/log_err_missing.txt delete mode 100644 27-functional-programming/log-parser-exp/log_err_negative.txt delete mode 100644 27-functional-programming/log-parser-exp/log_err_str.txt delete mode 100644 27-functional-programming/log-parser-exp/main.go delete mode 100644 27-functional-programming/log-parser-exp/pipeline.go delete mode 100644 27-functional-programming/log-parser-exp/result.go delete mode 100644 27-functional-programming/log-parser-exp/textreader.go delete mode 100644 27-functional-programming/log-parser-exp/textreaderfast.go delete mode 100644 27-functional-programming/log-parser-exp/textwriter.go delete mode 100644 29-interfaces/logparser-funcs/log.txt delete mode 100644 29-interfaces/logparser-funcs/log_err_missing.txt delete mode 100644 29-interfaces/logparser-funcs/log_err_negative.txt delete mode 100644 29-interfaces/logparser-funcs/log_err_str.txt delete mode 100644 29-interfaces/logparser-funcs/main.go delete mode 100644 29-interfaces/logparser-funcs/parser.go delete mode 100644 29-interfaces/logparser-funcs/result.go delete mode 100644 29-interfaces/logparser-funcs/summarize.go delete mode 100644 29-interfaces/logparser-funcs/summary.go delete mode 100644 29-interfaces/logparser-nopkg/log.txt delete mode 100644 29-interfaces/logparser-nopkg/log_err_missing.txt delete mode 100644 29-interfaces/logparser-nopkg/log_err_negative.txt delete mode 100644 29-interfaces/logparser-nopkg/log_err_str.txt delete mode 100644 29-interfaces/logparser-nopkg/main.go delete mode 100644 29-interfaces/logparser-nopkg/parser.go delete mode 100644 29-interfaces/logparser-nopkg/result.go delete mode 100644 29-interfaces/logparser-nopkg/summarize.go delete mode 100644 29-interfaces/logparser-nopkg/summary.go delete mode 100644 29-interfaces/logparser-pkg/log.txt delete mode 100644 29-interfaces/logparser-pkg/log_err_missing.txt delete mode 100644 29-interfaces/logparser-pkg/log_err_negative.txt delete mode 100644 29-interfaces/logparser-pkg/log_err_str.txt delete mode 100644 29-interfaces/logparser-pkg/main.go delete mode 100644 29-interfaces/logparser-pkg/report/parser.go delete mode 100644 29-interfaces/logparser-pkg/report/result.go delete mode 100644 29-interfaces/logparser-pkg/report/summary.go delete mode 100644 29-interfaces/logparser-pkg/summarize.go delete mode 100644 29-interfaces/logparser-testing/log.txt delete mode 100644 29-interfaces/logparser-testing/log_err_missing.txt delete mode 100644 29-interfaces/logparser-testing/log_err_negative.txt delete mode 100644 29-interfaces/logparser-testing/log_err_str.txt delete mode 100644 29-interfaces/logparser-testing/main.go delete mode 100644 29-interfaces/logparser-testing/main_test.go delete mode 100644 29-interfaces/logparser-testing/report/parser.go delete mode 100644 29-interfaces/logparser-testing/report/parser_test.go delete mode 100644 29-interfaces/logparser-testing/report/result.go delete mode 100644 29-interfaces/logparser-testing/report/summary.go delete mode 100644 29-interfaces/logparser-testing/report/summary_test.go delete mode 100644 29-interfaces/logparser-testing/summarize.go rename {31-concurrency => concurrency}/xxx-monte-carlo/main.go (100%) rename {28-error-handling => error-handling}/01-deferred-funcs/main.go (100%) rename {28-error-handling => error-handling}/02-png-detector/main.go (100%) rename {28-error-handling => error-handling}/02-png-detector/pngs/cups-jpg.png (100%) rename {28-error-handling => error-handling}/02-png-detector/pngs/empty.png (100%) rename {28-error-handling => error-handling}/02-png-detector/pngs/forest-jpg.png (100%) rename {28-error-handling => error-handling}/02-png-detector/pngs/golden.png (100%) rename {28-error-handling => error-handling}/02-png-detector/pngs/shakespeare-text.png (100%) rename {28-error-handling => error-handling}/02-png-detector/pngs/work.png (100%) rename {28-error-handling => error-handling}/03-png-detector-with-panic/main.go (100%) rename {28-error-handling => error-handling}/03-png-detector-with-panic/pngs/cups-jpg.png (100%) rename {28-error-handling => error-handling}/03-png-detector-with-panic/pngs/empty.png (100%) rename {28-error-handling => error-handling}/03-png-detector-with-panic/pngs/forest-jpg.png (100%) rename {28-error-handling => error-handling}/03-png-detector-with-panic/pngs/golden.png (100%) rename {28-error-handling => error-handling}/03-png-detector-with-panic/pngs/shakespeare-text.png (100%) rename {28-error-handling => error-handling}/03-png-detector-with-panic/pngs/work.png (100%) rename {28-error-handling => error-handling}/04-image-detector-recover/main.go (100%) rename {28-error-handling => error-handling}/04-image-detector-recover/pngs/cups-jpg.png (100%) rename {28-error-handling => error-handling}/04-image-detector-recover/pngs/empty.png (100%) rename {28-error-handling => error-handling}/04-image-detector-recover/pngs/forest-jpg.png (100%) rename {28-error-handling => error-handling}/04-image-detector-recover/pngs/golden.png (100%) rename {28-error-handling => error-handling}/04-image-detector-recover/pngs/shakespeare-text.png (100%) rename {28-error-handling => error-handling}/04-image-detector-recover/pngs/work.png (100%) rename {28-error-handling => error-handling}/04b-named-params/main.go (100%) rename {28-error-handling => error-handling}/04b-named-params/pngs/cups-jpg.png (100%) rename {28-error-handling => error-handling}/04b-named-params/pngs/empty.png (100%) rename {28-error-handling => error-handling}/04b-named-params/pngs/forest-jpg.png (100%) rename {28-error-handling => error-handling}/04b-named-params/pngs/golden.png (100%) rename {28-error-handling => error-handling}/04b-named-params/pngs/shakespeare-text.png (100%) rename {28-error-handling => error-handling}/04b-named-params/pngs/work.png (100%) rename {28-error-handling => error-handling}/exercises/01-refactor/main.go (100%) rename {28-error-handling => error-handling}/exercises/01-refactor/solution/main.go (100%) rename {28-error-handling => error-handling}/exercises/README.md (100%) diff --git a/27-functional-programming/_legacy/01-variadic-funcs/main.go b/27-functional-programming/_legacy/01-variadic-funcs/main.go deleted file mode 100644 index 6dad71d..0000000 --- a/27-functional-programming/_legacy/01-variadic-funcs/main.go +++ /dev/null @@ -1,73 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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 -} diff --git a/27-functional-programming/_legacy/02-func-values/main.go b/27-functional-programming/_legacy/02-func-values/main.go deleted file mode 100644 index e0f4ac4..0000000 --- a/27-functional-programming/_legacy/02-func-values/main.go +++ /dev/null @@ -1,52 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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) -} diff --git a/27-functional-programming/_legacy/03-func-to-func/main.go b/27-functional-programming/_legacy/03-func-to-func/main.go deleted file mode 100644 index d8102be..0000000 --- a/27-functional-programming/_legacy/03-func-to-func/main.go +++ /dev/null @@ -1,82 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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) -} diff --git a/27-functional-programming/_legacy/04-closures/main.go b/27-functional-programming/_legacy/04-closures/main.go deleted file mode 100644 index 9a62a75..0000000 --- a/27-functional-programming/_legacy/04-closures/main.go +++ /dev/null @@ -1,76 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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 -} diff --git a/27-functional-programming/_legacy/05-higher-order-funcs/main.go b/27-functional-programming/_legacy/05-higher-order-funcs/main.go deleted file mode 100644 index ef5da4c..0000000 --- a/27-functional-programming/_legacy/05-higher-order-funcs/main.go +++ /dev/null @@ -1,58 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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 } diff --git a/27-functional-programming/_legacy/06-functional-programming/main.go b/27-functional-programming/_legacy/06-functional-programming/main.go deleted file mode 100644 index 277e483..0000000 --- a/27-functional-programming/_legacy/06-functional-programming/main.go +++ /dev/null @@ -1,97 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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 } diff --git a/27-functional-programming/log-parser-exp/Makefile b/27-functional-programming/log-parser-exp/Makefile deleted file mode 100644 index 1a795c2..0000000 --- a/27-functional-programming/log-parser-exp/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -SHELL := /bin/bash -LINES = $$(wc -l log.txt | cut -f1 -d' ') -ECHO_LINES = echo -e ">> log.txt has $(LINES) lines" - -s: - time go run . < log.txt - -r: - go run . < log.txt - -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) - -lines: - @$(ECHO_LINES) \ No newline at end of file diff --git a/27-functional-programming/log-parser-exp/field.go b/27-functional-programming/log-parser-exp/field.go deleted file mode 100644 index 7881c1e..0000000 --- a/27-functional-programming/log-parser-exp/field.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "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 n < 0 || err != nil { - f.err = fmt.Errorf("incorrect field -> %q = %q", name, val) - } - return n -} diff --git a/27-functional-programming/log-parser-exp/filters.go b/27-functional-programming/log-parser-exp/filters.go deleted file mode 100644 index fe16049..0000000 --- a/27-functional-programming/log-parser-exp/filters.go +++ /dev/null @@ -1,34 +0,0 @@ -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") -} diff --git a/27-functional-programming/log-parser-exp/groupers.go b/27-functional-programming/log-parser-exp/groupers.go deleted file mode 100644 index d46ad56..0000000 --- a/27-functional-programming/log-parser-exp/groupers.go +++ /dev/null @@ -1,20 +0,0 @@ -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 "" -} diff --git a/27-functional-programming/log-parser-exp/log.txt b/27-functional-programming/log-parser-exp/log.txt deleted file mode 100644 index fa57104..0000000 --- a/27-functional-programming/log-parser-exp/log.txt +++ /dev/null @@ -1,16 +0,0 @@ -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 \ No newline at end of file diff --git a/27-functional-programming/log-parser-exp/log_err_missing.txt b/27-functional-programming/log-parser-exp/log_err_missing.txt deleted file mode 100644 index 01f606f..0000000 --- a/27-functional-programming/log-parser-exp/log_err_missing.txt +++ /dev/null @@ -1,16 +0,0 @@ -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 diff --git a/27-functional-programming/log-parser-exp/log_err_negative.txt b/27-functional-programming/log-parser-exp/log_err_negative.txt deleted file mode 100644 index d84023e..0000000 --- a/27-functional-programming/log-parser-exp/log_err_negative.txt +++ /dev/null @@ -1,16 +0,0 @@ -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 diff --git a/27-functional-programming/log-parser-exp/log_err_str.txt b/27-functional-programming/log-parser-exp/log_err_str.txt deleted file mode 100644 index 20272ab..0000000 --- a/27-functional-programming/log-parser-exp/log_err_str.txt +++ /dev/null @@ -1,16 +0,0 @@ -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 \ No newline at end of file diff --git a/27-functional-programming/log-parser-exp/main.go b/27-functional-programming/log-parser-exp/main.go deleted file mode 100644 index 77bfc34..0000000 --- a/27-functional-programming/log-parser-exp/main.go +++ /dev/null @@ -1,59 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "fmt" -) - -func main() { - defer recoverErr() - - _, err := newPipeline(). - // from(fastTextReader(os.Stdin)). - filterBy(notUsing(domainExtFilter("com", "io"))). - groupBy(domainGrouper). - start() - - if err != nil { - fmt.Println("> Err:", err) - } -} - -func recoverErr() { - val := recover() - - if val == nil { - return - } - - fmt.Println("> Error occurred:", val) -} - -/* -newReport -> report.New(). -Result -> report.Line - -notUsing = report.Not - -pl := newPipeline(pipeOpts{ - from: fastTextReader(os.Stdin), - filterBy: notUsing(domainExtFilter("com", "io")), - groupBy: domainGrouper, -}) - -err := pl.start() - -_, err := report.New(). - From(report.TextReader(os.Stdin)). - To(report.TextWriter(os.Stdout)). - // FilterBy(report.OrgDomainsFilter). - FilterBy(notUsing(report.DomainExtFilter("com", "io"))). - GroupBy(report.DomainGrouper). - Start() -*/ diff --git a/27-functional-programming/log-parser-exp/pipeline.go b/27-functional-programming/log-parser-exp/pipeline.go deleted file mode 100644 index 24e2f46..0000000 --- a/27-functional-programming/log-parser-exp/pipeline.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - "fmt" - "os" - "time" -) - -type ( - inputFn func() ([]result, error) - outputFn func([]result) error - filterFn func(result) (include bool) - groupFn func(result) (key string) -) - -type pipeline struct { - input inputFn - filter filterFn - groupKey groupFn - output outputFn -} - -func newPipeline() *pipeline { - return &pipeline{ - filter: noopFilter, - groupKey: noopGrouper, - input: textReader(os.Stdin), - output: textWriter(os.Stdout), - } -} - -func (p *pipeline) from(fn inputFn) *pipeline { p.input = fn; return p } -func (p *pipeline) to(fn outputFn) *pipeline { p.output = fn; return p } -func (p *pipeline) filterBy(fn filterFn) *pipeline { p.filter = fn; return p } -func (p *pipeline) groupBy(fn groupFn) *pipeline { p.groupKey = fn; return p } - -func (p *pipeline) start() ([]result, error) { - res, err := p.input() - if err != nil { - return nil, err - } - - gres := make(map[string]result) - - for _, r := range res { - if !p.filter(r) { - continue - } - - k := p.groupKey(r) - gres[k] = r.add(gres[k]) - } - - var out []result - for _, v := range gres { - out = append(out, v) - } - - err = p.output(out) - - return out, err -} - -// TODO: remove me -func measure(name string) func() { - start := time.Now() - return func() { - fmt.Printf("%s took %v\n", name, time.Since(start)) - } -} diff --git a/27-functional-programming/log-parser-exp/result.go b/27-functional-programming/log-parser-exp/result.go deleted file mode 100644 index 61a35e5..0000000 --- a/27-functional-programming/log-parser-exp/result.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "fmt" -) - -// result stores the parsed result for a domain -type result struct { - domain string - page string - visits int - uniques int -} - -// parseFields parses and returns the parsing result -func parseFields(fields []string) (r result, err error) { - if len(fields) != 4 { - return r, fmt.Errorf("wrong number of fields -> %v", 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 -} - -// add adds the metrics of another result to the result -func (r result) add(other result) result { - r.visits += other.visits - r.uniques += other.uniques - return r -} diff --git a/27-functional-programming/log-parser-exp/textreader.go b/27-functional-programming/log-parser-exp/textreader.go deleted file mode 100644 index 3654093..0000000 --- a/27-functional-programming/log-parser-exp/textreader.go +++ /dev/null @@ -1,38 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "bufio" - "fmt" - "io" - "strings" -) - -func textReader(r io.Reader) inputFn { - return func() ([]result, error) { - return parseText(bufio.NewScanner(r)) - } -} - -// TODO: custom error type for line information -func parseText(in *bufio.Scanner) ([]result, error) { - var res []result - - for l := 1; in.Scan(); l++ { - fields := strings.Fields(in.Text()) - r, err := parseFields(fields) - - if err != nil { - return nil, fmt.Errorf("line %d: %v", l, err) - } - res = append(res, r) - } - - return res, in.Err() -} diff --git a/27-functional-programming/log-parser-exp/textreaderfast.go b/27-functional-programming/log-parser-exp/textreaderfast.go deleted file mode 100644 index 9326106..0000000 --- a/27-functional-programming/log-parser-exp/textreaderfast.go +++ /dev/null @@ -1,129 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "bufio" - "bytes" - "errors" - "fmt" - "io" - "os" -) - -// this could be made faster. -// currently, it's 30-35% faster. -// -// so, what's different than the textreader? -// -// + creates the buffers specific to the input file/stdin size -// + manually parses the fields: instead of strings.Fields -// + gets the lines using scanner's Bytes() method: instead of Text() -// + uses a manual atoi -// + - -func fastTextReader(r io.Reader) inputFn { - return func() ([]result, error) { - // first: count the lines, so the parseText can create - // enough buffer. - var buf bytes.Buffer - l, err := countLines(io.TeeReader(r, &buf)) - if err != nil { - return nil, err - } - - return fastParseText(bufio.NewScanner(&buf), l) - } -} - -func fastParseText(in *bufio.Scanner, nlines int) ([]result, error) { - // needs to know the number of total lines in the file - res := make([]result, 0, nlines) - - for l := 0; in.Scan(); l++ { - _ = in.Bytes() - r, err := fastParseFields(in.Bytes()) - // r, err := result{"foo.com", "/bar", 10, 10}, error(nil) - - if err != nil { - return nil, fmt.Errorf("line %d: %v", l, err) - } - res = append(res, r) - } - - return res, in.Err() -} - -func fastParseFields(data []byte) (res result, err error) { - var field int - - for i, last := 0, 0; i < len(data); i++ { - done := len(data) == i+1 - - if c := data[i]; c == ' ' || done { - if done { - i = len(data) - } - - switch field { - case 0: - res.domain = string(data[last:i]) - case 1: - res.page = string(data[last:i]) - case 2: - res.visits, err = atoi(data[last:i]) - case 3: - res.uniques, err = atoi(data[last:i]) - } - - if err != nil { - return res, err - } - - last = i + 1 - field++ - } - } - - if field != 4 { - return result{}, errors.New("wrong number of fields") - } - return res, nil -} - -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 -} - -func countLines(r io.Reader) (int, error) { - var ( - lines int - buf = make([]byte, os.Getpagesize()) // read via 16 KB blocks - ) - - for { - n, err := r.Read(buf) - lines += bytes.Count(buf[:n], []byte{'\n'}) - - if err == io.EOF { - return lines, nil - } - - if err != nil { - return lines, err - } - } -} diff --git a/27-functional-programming/log-parser-exp/textwriter.go b/27-functional-programming/log-parser-exp/textwriter.go deleted file mode 100644 index 3788f64..0000000 --- a/27-functional-programming/log-parser-exp/textwriter.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "fmt" - "io" - "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 - dashLength = 58 -) - -func textWriter(w io.Writer) outputFn { - return func(results []result) error { - fmt.Fprintf(w, header, "DOMAINS", "PAGES", "VISITS", "UNIQUES") - fmt.Fprintln(w, strings.Repeat("-", dashLength)) - - var total result - for _, r := range results { - 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 - } -} diff --git a/29-interfaces/logparser-funcs/log.txt b/29-interfaces/logparser-funcs/log.txt deleted file mode 100644 index fb2432b..0000000 --- a/29-interfaces/logparser-funcs/log.txt +++ /dev/null @@ -1,6 +0,0 @@ -learngoprogramming.com 10 -learngoprogramming.com 10 -golang.org 4 -golang.org 6 -blog.golang.org 20 -blog.golang.org 10 \ No newline at end of file diff --git a/29-interfaces/logparser-funcs/log_err_missing.txt b/29-interfaces/logparser-funcs/log_err_missing.txt deleted file mode 100644 index fd8eff4..0000000 --- a/29-interfaces/logparser-funcs/log_err_missing.txt +++ /dev/null @@ -1,6 +0,0 @@ -learngoprogramming.com 10 -learngoprogramming.com 10 -golang.org -golang.org 6 -blog.golang.org 20 -blog.golang.org 10 \ No newline at end of file diff --git a/29-interfaces/logparser-funcs/log_err_negative.txt b/29-interfaces/logparser-funcs/log_err_negative.txt deleted file mode 100644 index 60485c0..0000000 --- a/29-interfaces/logparser-funcs/log_err_negative.txt +++ /dev/null @@ -1,6 +0,0 @@ -learngoprogramming.com 10 -learngoprogramming.com 10 -golang.org -100 -golang.org 6 -blog.golang.org 20 -blog.golang.org 10 \ No newline at end of file diff --git a/29-interfaces/logparser-funcs/log_err_str.txt b/29-interfaces/logparser-funcs/log_err_str.txt deleted file mode 100644 index 3a55bd7..0000000 --- a/29-interfaces/logparser-funcs/log_err_str.txt +++ /dev/null @@ -1,6 +0,0 @@ -learngoprogramming.com 10 -learngoprogramming.com 10 -golang.org FOUR -golang.org 6 -blog.golang.org 20 -blog.golang.org 10 \ No newline at end of file diff --git a/29-interfaces/logparser-funcs/main.go b/29-interfaces/logparser-funcs/main.go deleted file mode 100644 index 2ff0a0b..0000000 --- a/29-interfaces/logparser-funcs/main.go +++ /dev/null @@ -1,26 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "bufio" - "os" -) - -func main() { - p := newParser() - - in := bufio.NewScanner(os.Stdin) - for in.Scan() { - res := parse(p, in.Text()) - updateSummary(p.summary, res) - } - - summarize(summarizeParse(p)) - dumpErrs(errParse(p), in.Err()) -} diff --git a/29-interfaces/logparser-funcs/parser.go b/29-interfaces/logparser-funcs/parser.go deleted file mode 100644 index 478a1af..0000000 --- a/29-interfaces/logparser-funcs/parser.go +++ /dev/null @@ -1,70 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "fmt" - "strconv" - "strings" -) - -// 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 newParser() *parser { - return &parser{summary: newSummary()} -} - -// parse parses a log line and adds it to the summary. -func parse(p *parser, line string) (r result) { - // if there was an error do not continue - if p.lerr != nil { - return - } - - // chain the parser's error to the result's - r = parseLine(p, line) - if p.lines++; p.lerr != nil { - p.lerr = fmt.Errorf("line #%d: %s", p.lines, p.lerr) - } - return -} - -// parse parses a single log line -func parseLine(p *parser, line string) (r result) { - fields := strings.Fields(line) - if len(fields) != 2 { - // p.lerr = fmt.Errorf("wrong input: %v (line #%d)", fields, p.lines) - p.lerr = fmt.Errorf("missing fields: %v", fields) - return - } - - r.domain = fields[0] - r.visits, p.lerr = strconv.Atoi(fields[1]) - - if r.visits < 0 || p.lerr != nil { - p.lerr = fmt.Errorf("incorrect visits: %q", fields[1]) - } - return -} - -// summarizeParse summarizes the parsing results. -// Only use it after the parsing is done. -func summarizeParse(p *parser) *summary { - return p.summary -} - -// errParse returns the last error encountered -func errParse(p *parser) error { - return p.lerr -} diff --git a/29-interfaces/logparser-funcs/result.go b/29-interfaces/logparser-funcs/result.go deleted file mode 100644 index fac18dc..0000000 --- a/29-interfaces/logparser-funcs/result.go +++ /dev/null @@ -1,27 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -// 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 - visits int - // add more metrics if needed -} - -// add adds the metrics of another result to itself and returns a new Result -func addResult(r result, other result) result { - return result{ - domain: r.domain, - visits: r.visits + other.visits, - } -} diff --git a/29-interfaces/logparser-funcs/summarize.go b/29-interfaces/logparser-funcs/summarize.go deleted file mode 100644 index 9a10929..0000000 --- a/29-interfaces/logparser-funcs/summarize.go +++ /dev/null @@ -1,36 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "fmt" - "strings" -) - -// summarize prints the parsing results. -func summarize(s *summary) { - fmt.Printf("%-30s %10s\n", "DOMAIN", "VISITS") - fmt.Println(strings.Repeat("-", 45)) - - for next, cur := iteratorSummary(s); next(); { - r := cur() - fmt.Printf("%-30s %10d\n", r.domain, r.visits) - } - - t := totalsSummary(s) - fmt.Printf("\n"+"%-30s %10d\n", "TOTAL", t.visits) -} - -// this variadic func simplifies the multiple error handling -func dumpErrs(errs ...error) { - for _, err := range errs { - if err != nil { - fmt.Printf("> Err: %s\n", err) - } - } -} diff --git a/29-interfaces/logparser-funcs/summary.go b/29-interfaces/logparser-funcs/summary.go deleted file mode 100644 index b312ea8..0000000 --- a/29-interfaces/logparser-funcs/summary.go +++ /dev/null @@ -1,70 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -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)} -} - -// updateSummary updates the report for the given parsing result -func updateSummary(s *summary, 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 = addResult(s.total, r) - s.sum[domain] = addResult(r, s.sum[domain]) -} - -// iteratorSummary returns `next()` to detect when the iteration ends, -// and a `cur()` to return the current result. -// iterator iterates sorted by domains. -func iteratorSummary(s *summary) (next func() bool, cur func() result) { - sort.Strings(s.domains) - - // remember the last iterated result - var last int - - next = func() bool { - // done := len(s.domains) > last - // last++ - // return done - 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 -} - -// totalsSummary returns the total metrics -func totalsSummary(s *summary) result { - return s.total -} diff --git a/29-interfaces/logparser-nopkg/log.txt b/29-interfaces/logparser-nopkg/log.txt deleted file mode 100644 index b449a83..0000000 --- a/29-interfaces/logparser-nopkg/log.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-nopkg/log_err_missing.txt b/29-interfaces/logparser-nopkg/log_err_missing.txt deleted file mode 100644 index 8fbe528..0000000 --- a/29-interfaces/logparser-nopkg/log_err_missing.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-nopkg/log_err_negative.txt b/29-interfaces/logparser-nopkg/log_err_negative.txt deleted file mode 100644 index b099716..0000000 --- a/29-interfaces/logparser-nopkg/log_err_negative.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-nopkg/log_err_str.txt b/29-interfaces/logparser-nopkg/log_err_str.txt deleted file mode 100644 index 4ccb676..0000000 --- a/29-interfaces/logparser-nopkg/log_err_str.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-nopkg/main.go b/29-interfaces/logparser-nopkg/main.go deleted file mode 100644 index b53bc82..0000000 --- a/29-interfaces/logparser-nopkg/main.go +++ /dev/null @@ -1,24 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "bufio" - "os" -) - -func main() { - p := newParser() - - in := bufio.NewScanner(os.Stdin) - for in.Scan() { - p.parse(in.Text()) - } - - summarize(p.summarize(), p.err(), in.Err()) -} diff --git a/29-interfaces/logparser-nopkg/parser.go b/29-interfaces/logparser-nopkg/parser.go deleted file mode 100644 index 46d31ab..0000000 --- a/29-interfaces/logparser-nopkg/parser.go +++ /dev/null @@ -1,52 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -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 newParser() *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 := parseLine(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 -} diff --git a/29-interfaces/logparser-nopkg/result.go b/29-interfaces/logparser-nopkg/result.go deleted file mode 100644 index eefeca1..0000000 --- a/29-interfaces/logparser-nopkg/result.go +++ /dev/null @@ -1,60 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -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 - visits int - timeSpent int - // 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 parseLine(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 -} diff --git a/29-interfaces/logparser-nopkg/summarize.go b/29-interfaces/logparser-nopkg/summarize.go deleted file mode 100644 index ee61cec..0000000 --- a/29-interfaces/logparser-nopkg/summarize.go +++ /dev/null @@ -1,51 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "fmt" - "strings" -) - -// 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 *summary, errors ...error) { - if errs(errors...) { - return - } - - 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.totals() - 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 -} diff --git a/29-interfaces/logparser-nopkg/summary.go b/29-interfaces/logparser-nopkg/summary.go deleted file mode 100644 index 1dfd6f0..0000000 --- a/29-interfaces/logparser-nopkg/summary.go +++ /dev/null @@ -1,70 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -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 { - // done := len(s.domains) > last - // last++ - // return done - 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 -} - -// totals returns the total metrics -func (s *summary) totals() result { - return s.total -} diff --git a/29-interfaces/logparser-pkg/log.txt b/29-interfaces/logparser-pkg/log.txt deleted file mode 100644 index b449a83..0000000 --- a/29-interfaces/logparser-pkg/log.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-pkg/log_err_missing.txt b/29-interfaces/logparser-pkg/log_err_missing.txt deleted file mode 100644 index 8fbe528..0000000 --- a/29-interfaces/logparser-pkg/log_err_missing.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-pkg/log_err_negative.txt b/29-interfaces/logparser-pkg/log_err_negative.txt deleted file mode 100644 index b099716..0000000 --- a/29-interfaces/logparser-pkg/log_err_negative.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-pkg/log_err_str.txt b/29-interfaces/logparser-pkg/log_err_str.txt deleted file mode 100644 index 4ccb676..0000000 --- a/29-interfaces/logparser-pkg/log_err_str.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-pkg/main.go b/29-interfaces/logparser-pkg/main.go deleted file mode 100644 index 921b77a..0000000 --- a/29-interfaces/logparser-pkg/main.go +++ /dev/null @@ -1,26 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "bufio" - "os" - - "github.com/inancgumus/learngo/29-interfaces/logparser-pkg/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()) -} diff --git a/29-interfaces/logparser-pkg/report/parser.go b/29-interfaces/logparser-pkg/report/parser.go deleted file mode 100644 index 59b12fe..0000000 --- a/29-interfaces/logparser-pkg/report/parser.go +++ /dev/null @@ -1,52 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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 -} diff --git a/29-interfaces/logparser-pkg/report/result.go b/29-interfaces/logparser-pkg/report/result.go deleted file mode 100644 index 95e0022..0000000 --- a/29-interfaces/logparser-pkg/report/result.go +++ /dev/null @@ -1,60 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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 -} diff --git a/29-interfaces/logparser-pkg/report/summary.go b/29-interfaces/logparser-pkg/report/summary.go deleted file mode 100644 index 9860e5e..0000000 --- a/29-interfaces/logparser-pkg/report/summary.go +++ /dev/null @@ -1,85 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package report - -import ( - "encoding/json" - "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 -} - -// 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}, - }) -} diff --git a/29-interfaces/logparser-pkg/summarize.go b/29-interfaces/logparser-pkg/summarize.go deleted file mode 100644 index e059e73..0000000 --- a/29-interfaces/logparser-pkg/summarize.go +++ /dev/null @@ -1,73 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "encoding/json" - "fmt" - "os" - "strings" - - "github.com/inancgumus/learngo/29-interfaces/logparser-pkg/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 -} diff --git a/29-interfaces/logparser-testing/log.txt b/29-interfaces/logparser-testing/log.txt deleted file mode 100644 index b449a83..0000000 --- a/29-interfaces/logparser-testing/log.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-testing/log_err_missing.txt b/29-interfaces/logparser-testing/log_err_missing.txt deleted file mode 100644 index 8fbe528..0000000 --- a/29-interfaces/logparser-testing/log_err_missing.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-testing/log_err_negative.txt b/29-interfaces/logparser-testing/log_err_negative.txt deleted file mode 100644 index b099716..0000000 --- a/29-interfaces/logparser-testing/log_err_negative.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-testing/log_err_str.txt b/29-interfaces/logparser-testing/log_err_str.txt deleted file mode 100644 index 4ccb676..0000000 --- a/29-interfaces/logparser-testing/log_err_str.txt +++ /dev/null @@ -1,6 +0,0 @@ -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 \ No newline at end of file diff --git a/29-interfaces/logparser-testing/main.go b/29-interfaces/logparser-testing/main.go deleted file mode 100644 index 637afc6..0000000 --- a/29-interfaces/logparser-testing/main.go +++ /dev/null @@ -1,26 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "bufio" - "os" - - "github.com/inancgumus/learngo/29-interfaces/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()) -} diff --git a/29-interfaces/logparser-testing/main_test.go b/29-interfaces/logparser-testing/main_test.go deleted file mode 100644 index b706f78..0000000 --- a/29-interfaces/logparser-testing/main_test.go +++ /dev/null @@ -1,59 +0,0 @@ -// +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) - } -} diff --git a/29-interfaces/logparser-testing/report/parser.go b/29-interfaces/logparser-testing/report/parser.go deleted file mode 100644 index 59b12fe..0000000 --- a/29-interfaces/logparser-testing/report/parser.go +++ /dev/null @@ -1,52 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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 -} diff --git a/29-interfaces/logparser-testing/report/parser_test.go b/29-interfaces/logparser-testing/report/parser_test.go deleted file mode 100644 index b0a1dce..0000000 --- a/29-interfaces/logparser-testing/report/parser_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package report_test - -import ( - "strings" - "testing" - - "github.com/inancgumus/learngo/28-methods/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) - } - }) - } -} diff --git a/29-interfaces/logparser-testing/report/result.go b/29-interfaces/logparser-testing/report/result.go deleted file mode 100644 index 95e0022..0000000 --- a/29-interfaces/logparser-testing/report/result.go +++ /dev/null @@ -1,60 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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 -} diff --git a/29-interfaces/logparser-testing/report/summary.go b/29-interfaces/logparser-testing/report/summary.go deleted file mode 100644 index f1b88bd..0000000 --- a/29-interfaces/logparser-testing/report/summary.go +++ /dev/null @@ -1,86 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -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}, -// }) -// } diff --git a/29-interfaces/logparser-testing/report/summary_test.go b/29-interfaces/logparser-testing/report/summary_test.go deleted file mode 100644 index 2a0fc50..0000000 --- a/29-interfaces/logparser-testing/report/summary_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package report_test - -import ( - "testing" - - "github.com/inancgumus/learngo/28-methods/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) - } - }) - } -} diff --git a/29-interfaces/logparser-testing/summarize.go b/29-interfaces/logparser-testing/summarize.go deleted file mode 100644 index 2f2eb8b..0000000 --- a/29-interfaces/logparser-testing/summarize.go +++ /dev/null @@ -1,73 +0,0 @@ -// For more tutorials: https://blog.learngoprogramming.com -// -// Copyright © 2018 Inanc Gumus -// Learn Go Programming Course -// License: https://creativecommons.org/licenses/by-nc-sa/4.0/ -// - -package main - -import ( - "encoding/json" - "fmt" - "os" - "strings" - - "github.com/inancgumus/learngo/29-interfaces/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 -} diff --git a/31-concurrency/xxx-monte-carlo/main.go b/concurrency/xxx-monte-carlo/main.go similarity index 100% rename from 31-concurrency/xxx-monte-carlo/main.go rename to concurrency/xxx-monte-carlo/main.go diff --git a/28-error-handling/01-deferred-funcs/main.go b/error-handling/01-deferred-funcs/main.go similarity index 100% rename from 28-error-handling/01-deferred-funcs/main.go rename to error-handling/01-deferred-funcs/main.go diff --git a/28-error-handling/02-png-detector/main.go b/error-handling/02-png-detector/main.go similarity index 100% rename from 28-error-handling/02-png-detector/main.go rename to error-handling/02-png-detector/main.go diff --git a/28-error-handling/02-png-detector/pngs/cups-jpg.png b/error-handling/02-png-detector/pngs/cups-jpg.png similarity index 100% rename from 28-error-handling/02-png-detector/pngs/cups-jpg.png rename to error-handling/02-png-detector/pngs/cups-jpg.png diff --git a/28-error-handling/02-png-detector/pngs/empty.png b/error-handling/02-png-detector/pngs/empty.png similarity index 100% rename from 28-error-handling/02-png-detector/pngs/empty.png rename to error-handling/02-png-detector/pngs/empty.png diff --git a/28-error-handling/02-png-detector/pngs/forest-jpg.png b/error-handling/02-png-detector/pngs/forest-jpg.png similarity index 100% rename from 28-error-handling/02-png-detector/pngs/forest-jpg.png rename to error-handling/02-png-detector/pngs/forest-jpg.png diff --git a/28-error-handling/02-png-detector/pngs/golden.png b/error-handling/02-png-detector/pngs/golden.png similarity index 100% rename from 28-error-handling/02-png-detector/pngs/golden.png rename to error-handling/02-png-detector/pngs/golden.png diff --git a/28-error-handling/02-png-detector/pngs/shakespeare-text.png b/error-handling/02-png-detector/pngs/shakespeare-text.png similarity index 100% rename from 28-error-handling/02-png-detector/pngs/shakespeare-text.png rename to error-handling/02-png-detector/pngs/shakespeare-text.png diff --git a/28-error-handling/02-png-detector/pngs/work.png b/error-handling/02-png-detector/pngs/work.png similarity index 100% rename from 28-error-handling/02-png-detector/pngs/work.png rename to error-handling/02-png-detector/pngs/work.png diff --git a/28-error-handling/03-png-detector-with-panic/main.go b/error-handling/03-png-detector-with-panic/main.go similarity index 100% rename from 28-error-handling/03-png-detector-with-panic/main.go rename to error-handling/03-png-detector-with-panic/main.go diff --git a/28-error-handling/03-png-detector-with-panic/pngs/cups-jpg.png b/error-handling/03-png-detector-with-panic/pngs/cups-jpg.png similarity index 100% rename from 28-error-handling/03-png-detector-with-panic/pngs/cups-jpg.png rename to error-handling/03-png-detector-with-panic/pngs/cups-jpg.png diff --git a/28-error-handling/03-png-detector-with-panic/pngs/empty.png b/error-handling/03-png-detector-with-panic/pngs/empty.png similarity index 100% rename from 28-error-handling/03-png-detector-with-panic/pngs/empty.png rename to error-handling/03-png-detector-with-panic/pngs/empty.png diff --git a/28-error-handling/03-png-detector-with-panic/pngs/forest-jpg.png b/error-handling/03-png-detector-with-panic/pngs/forest-jpg.png similarity index 100% rename from 28-error-handling/03-png-detector-with-panic/pngs/forest-jpg.png rename to error-handling/03-png-detector-with-panic/pngs/forest-jpg.png diff --git a/28-error-handling/03-png-detector-with-panic/pngs/golden.png b/error-handling/03-png-detector-with-panic/pngs/golden.png similarity index 100% rename from 28-error-handling/03-png-detector-with-panic/pngs/golden.png rename to error-handling/03-png-detector-with-panic/pngs/golden.png diff --git a/28-error-handling/03-png-detector-with-panic/pngs/shakespeare-text.png b/error-handling/03-png-detector-with-panic/pngs/shakespeare-text.png similarity index 100% rename from 28-error-handling/03-png-detector-with-panic/pngs/shakespeare-text.png rename to error-handling/03-png-detector-with-panic/pngs/shakespeare-text.png diff --git a/28-error-handling/03-png-detector-with-panic/pngs/work.png b/error-handling/03-png-detector-with-panic/pngs/work.png similarity index 100% rename from 28-error-handling/03-png-detector-with-panic/pngs/work.png rename to error-handling/03-png-detector-with-panic/pngs/work.png diff --git a/28-error-handling/04-image-detector-recover/main.go b/error-handling/04-image-detector-recover/main.go similarity index 100% rename from 28-error-handling/04-image-detector-recover/main.go rename to error-handling/04-image-detector-recover/main.go diff --git a/28-error-handling/04-image-detector-recover/pngs/cups-jpg.png b/error-handling/04-image-detector-recover/pngs/cups-jpg.png similarity index 100% rename from 28-error-handling/04-image-detector-recover/pngs/cups-jpg.png rename to error-handling/04-image-detector-recover/pngs/cups-jpg.png diff --git a/28-error-handling/04-image-detector-recover/pngs/empty.png b/error-handling/04-image-detector-recover/pngs/empty.png similarity index 100% rename from 28-error-handling/04-image-detector-recover/pngs/empty.png rename to error-handling/04-image-detector-recover/pngs/empty.png diff --git a/28-error-handling/04-image-detector-recover/pngs/forest-jpg.png b/error-handling/04-image-detector-recover/pngs/forest-jpg.png similarity index 100% rename from 28-error-handling/04-image-detector-recover/pngs/forest-jpg.png rename to error-handling/04-image-detector-recover/pngs/forest-jpg.png diff --git a/28-error-handling/04-image-detector-recover/pngs/golden.png b/error-handling/04-image-detector-recover/pngs/golden.png similarity index 100% rename from 28-error-handling/04-image-detector-recover/pngs/golden.png rename to error-handling/04-image-detector-recover/pngs/golden.png diff --git a/28-error-handling/04-image-detector-recover/pngs/shakespeare-text.png b/error-handling/04-image-detector-recover/pngs/shakespeare-text.png similarity index 100% rename from 28-error-handling/04-image-detector-recover/pngs/shakespeare-text.png rename to error-handling/04-image-detector-recover/pngs/shakespeare-text.png diff --git a/28-error-handling/04-image-detector-recover/pngs/work.png b/error-handling/04-image-detector-recover/pngs/work.png similarity index 100% rename from 28-error-handling/04-image-detector-recover/pngs/work.png rename to error-handling/04-image-detector-recover/pngs/work.png diff --git a/28-error-handling/04b-named-params/main.go b/error-handling/04b-named-params/main.go similarity index 100% rename from 28-error-handling/04b-named-params/main.go rename to error-handling/04b-named-params/main.go diff --git a/28-error-handling/04b-named-params/pngs/cups-jpg.png b/error-handling/04b-named-params/pngs/cups-jpg.png similarity index 100% rename from 28-error-handling/04b-named-params/pngs/cups-jpg.png rename to error-handling/04b-named-params/pngs/cups-jpg.png diff --git a/28-error-handling/04b-named-params/pngs/empty.png b/error-handling/04b-named-params/pngs/empty.png similarity index 100% rename from 28-error-handling/04b-named-params/pngs/empty.png rename to error-handling/04b-named-params/pngs/empty.png diff --git a/28-error-handling/04b-named-params/pngs/forest-jpg.png b/error-handling/04b-named-params/pngs/forest-jpg.png similarity index 100% rename from 28-error-handling/04b-named-params/pngs/forest-jpg.png rename to error-handling/04b-named-params/pngs/forest-jpg.png diff --git a/28-error-handling/04b-named-params/pngs/golden.png b/error-handling/04b-named-params/pngs/golden.png similarity index 100% rename from 28-error-handling/04b-named-params/pngs/golden.png rename to error-handling/04b-named-params/pngs/golden.png diff --git a/28-error-handling/04b-named-params/pngs/shakespeare-text.png b/error-handling/04b-named-params/pngs/shakespeare-text.png similarity index 100% rename from 28-error-handling/04b-named-params/pngs/shakespeare-text.png rename to error-handling/04b-named-params/pngs/shakespeare-text.png diff --git a/28-error-handling/04b-named-params/pngs/work.png b/error-handling/04b-named-params/pngs/work.png similarity index 100% rename from 28-error-handling/04b-named-params/pngs/work.png rename to error-handling/04b-named-params/pngs/work.png diff --git a/28-error-handling/exercises/01-refactor/main.go b/error-handling/exercises/01-refactor/main.go similarity index 100% rename from 28-error-handling/exercises/01-refactor/main.go rename to error-handling/exercises/01-refactor/main.go diff --git a/28-error-handling/exercises/01-refactor/solution/main.go b/error-handling/exercises/01-refactor/solution/main.go similarity index 100% rename from 28-error-handling/exercises/01-refactor/solution/main.go rename to error-handling/exercises/01-refactor/solution/main.go diff --git a/28-error-handling/exercises/README.md b/error-handling/exercises/README.md similarity index 100% rename from 28-error-handling/exercises/README.md rename to error-handling/exercises/README.md