From 856c4aa8939436bbe5088cd2daaddc710f7bd009 Mon Sep 17 00:00:00 2001 From: Inanc Gumus Date: Tue, 30 Apr 2019 15:53:36 +0300 Subject: [PATCH] add: variadic funcs --- .../log-parser-to-variadic/log.txt | 6 ++ .../log_err_missing.txt | 6 ++ .../log_err_negative.txt | 6 ++ .../log-parser-to-variadic/log_err_str.txt | 6 ++ .../log-parser-to-variadic/main.go | 51 +++++++++++ .../log-parser-to-variadic/parser.go | 86 +++++++++++++++++++ .../01-variadic-funcs/main.go | 73 ++++++++++++++++ 7 files changed, 234 insertions(+) create mode 100644 27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log.txt create mode 100644 27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_missing.txt create mode 100644 27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_negative.txt create mode 100644 27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_str.txt create mode 100644 27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/main.go create mode 100644 27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/parser.go create mode 100644 27-functions-advanced/01-variadic-funcs/main.go diff --git a/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log.txt b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log.txt new file mode 100644 index 0000000..fb2432b --- /dev/null +++ b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log.txt @@ -0,0 +1,6 @@ +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/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_missing.txt b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_missing.txt new file mode 100644 index 0000000..fd8eff4 --- /dev/null +++ b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_missing.txt @@ -0,0 +1,6 @@ +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/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_negative.txt b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_negative.txt new file mode 100644 index 0000000..60485c0 --- /dev/null +++ b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_negative.txt @@ -0,0 +1,6 @@ +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/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_str.txt b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_str.txt new file mode 100644 index 0000000..3a55bd7 --- /dev/null +++ b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/log_err_str.txt @@ -0,0 +1,6 @@ +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/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/main.go b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/main.go new file mode 100644 index 0000000..a5a86d6 --- /dev/null +++ b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/main.go @@ -0,0 +1,51 @@ +// 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" + "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(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) + } + } +} diff --git a/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/parser.go b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/parser.go new file mode 100644 index 0000000..3c27940 --- /dev/null +++ b/27-functions-advanced/01-variadic-funcs/log-parser-to-variadic/parser.go @@ -0,0 +1,86 @@ +// 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" +) + +// 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 the errors for 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 +} diff --git a/27-functions-advanced/01-variadic-funcs/main.go b/27-functions-advanced/01-variadic-funcs/main.go new file mode 100644 index 0000000..6dad71d --- /dev/null +++ b/27-functions-advanced/01-variadic-funcs/main.go @@ -0,0 +1,73 @@ +// 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 +}