From 3a33312bdc733c7e89736f7c63e6012a8940cfe6 Mon Sep 17 00:00:00 2001 From: Inanc Gumus Date: Mon, 13 May 2019 18:22:49 +0300 Subject: [PATCH] add: calculator example to x-tba --- .../calc/01-shortdecl-int-conv/main.go | 16 +++++ x-tba/foundations/calc/02-if/main.go | 21 ++++++ x-tba/foundations/calc/03-floats-conv/main.go | 21 ++++++ .../calc/04-error-handling/main.go | 30 +++++++++ x-tba/foundations/calc/05-switch/main.go | 46 +++++++++++++ x-tba/foundations/calc/06-switch/main.go | 49 ++++++++++++++ x-tba/foundations/calc/07/main.go | 51 ++++++++++++++ x-tba/foundations/calc/08-funcs/main.go | 67 +++++++++++++++++++ .../foundations/calc/09-packages/calc/calc.go | 36 ++++++++++ x-tba/foundations/calc/09-packages/main.go | 50 ++++++++++++++ .../calc/calc-scanner/calculations.txt | 4 ++ x-tba/foundations/calc/calc-scanner/main.go | 66 ++++++++++++++++++ 12 files changed, 457 insertions(+) create mode 100644 x-tba/foundations/calc/01-shortdecl-int-conv/main.go create mode 100644 x-tba/foundations/calc/02-if/main.go create mode 100644 x-tba/foundations/calc/03-floats-conv/main.go create mode 100644 x-tba/foundations/calc/04-error-handling/main.go create mode 100644 x-tba/foundations/calc/05-switch/main.go create mode 100644 x-tba/foundations/calc/06-switch/main.go create mode 100644 x-tba/foundations/calc/07/main.go create mode 100644 x-tba/foundations/calc/08-funcs/main.go create mode 100644 x-tba/foundations/calc/09-packages/calc/calc.go create mode 100644 x-tba/foundations/calc/09-packages/main.go create mode 100644 x-tba/foundations/calc/calc-scanner/calculations.txt create mode 100644 x-tba/foundations/calc/calc-scanner/main.go diff --git a/x-tba/foundations/calc/01-shortdecl-int-conv/main.go b/x-tba/foundations/calc/01-shortdecl-int-conv/main.go new file mode 100644 index 0000000..7f61903 --- /dev/null +++ b/x-tba/foundations/calc/01-shortdecl-int-conv/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + // lesson: multi-return funcs, %v, and _ + + a, _ := strconv.Atoi(os.Args[1]) + b, _ := strconv.Atoi(os.Args[2]) + + fmt.Printf("%v + %v = %v\n", a, b, a+b) +} diff --git a/x-tba/foundations/calc/02-if/main.go b/x-tba/foundations/calc/02-if/main.go new file mode 100644 index 0000000..06696a3 --- /dev/null +++ b/x-tba/foundations/calc/02-if/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + // lesson: if + + if len(os.Args) != 3 { + fmt.Println("Usage: calc ") + return + } + + a, _ := strconv.Atoi(os.Args[1]) + b, _ := strconv.Atoi(os.Args[2]) + + fmt.Printf("%v + %v = %v\n", a, b, a+b) +} diff --git a/x-tba/foundations/calc/03-floats-conv/main.go b/x-tba/foundations/calc/03-floats-conv/main.go new file mode 100644 index 0000000..dda0068 --- /dev/null +++ b/x-tba/foundations/calc/03-floats-conv/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + // lesson: floats encompass integers too + + if len(os.Args) != 3 { + fmt.Println("Usage: calc ") + return + } + + a, _ := strconv.ParseFloat(os.Args[1], 64) + b, _ := strconv.ParseFloat(os.Args[2], 64) + + fmt.Printf("%v + %v = %v\n", a, b, a+b) +} diff --git a/x-tba/foundations/calc/04-error-handling/main.go b/x-tba/foundations/calc/04-error-handling/main.go new file mode 100644 index 0000000..6f79b95 --- /dev/null +++ b/x-tba/foundations/calc/04-error-handling/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + // lesson: error handling + short decl. assignment + + if len(os.Args) != 3 { + fmt.Println("Usage: calc ") + return + } + + a, err := strconv.ParseFloat(os.Args[1], 64) + if err != nil { + fmt.Println("Please provide a valid number") + return + } + + b, err := strconv.ParseFloat(os.Args[2], 64) + if err != nil { + fmt.Println("Please provide a valid number") + return + } + + fmt.Printf("%v + %v = %v\n", a, b, a+b) +} diff --git a/x-tba/foundations/calc/05-switch/main.go b/x-tba/foundations/calc/05-switch/main.go new file mode 100644 index 0000000..c9c43f8 --- /dev/null +++ b/x-tba/foundations/calc/05-switch/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + // lesson: switch + + if len(os.Args) != 4 { + fmt.Println("Usage: calc ") + return + } + + a, err := strconv.ParseFloat(os.Args[1], 64) + if err != nil { + fmt.Println("Please provide a valid number") + return + } + + b, err := strconv.ParseFloat(os.Args[3], 64) + if err != nil { + fmt.Println("Please provide a valid number") + return + } + + var ( + op = os.Args[2] + res float64 + ) + + switch op { + case "+": + res = a + b + case "-": + res = a - b + case "*": + res = a * b + case "/": + res = a / b + } + + fmt.Printf("%v %v %v = %v\n", a, op, b, res) +} diff --git a/x-tba/foundations/calc/06-switch/main.go b/x-tba/foundations/calc/06-switch/main.go new file mode 100644 index 0000000..aa030a3 --- /dev/null +++ b/x-tba/foundations/calc/06-switch/main.go @@ -0,0 +1,49 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + // lesson: switch default + multiple case + + if len(os.Args) != 4 { + fmt.Println("Usage: calc ") + return + } + + a, err := strconv.ParseFloat(os.Args[1], 64) + if err != nil { + fmt.Println("Please provide a valid number") + return + } + + b, err := strconv.ParseFloat(os.Args[3], 64) + if err != nil { + fmt.Println("Please provide a valid number") + return + } + + var ( + op = os.Args[2] + res float64 + ) + + switch op { + case "+", "plus": + op, res = "+", a+b + case "-", "minus": + op, res = "-", a-b + case "*", "times": + op, res = "*", a*b + case "/", "div": + op, res = "/", a/b + default: + fmt.Println("Please provide a valid operation.") + return + } + + fmt.Printf("%v %v %v = %v\n", a, op, b, res) +} diff --git a/x-tba/foundations/calc/07/main.go b/x-tba/foundations/calc/07/main.go new file mode 100644 index 0000000..78d9217 --- /dev/null +++ b/x-tba/foundations/calc/07/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "fmt" + "os" + "strconv" +) + +func main() { + // lesson: modulo operator and type conversion + + if len(os.Args) != 4 { + fmt.Println("Usage: calc ") + return + } + + a, err := strconv.ParseFloat(os.Args[1], 64) + if err != nil { + fmt.Println("Please provide a valid number") + return + } + + b, err := strconv.ParseFloat(os.Args[3], 64) + if err != nil { + fmt.Println("Please provide a valid number") + return + } + + var ( + op = os.Args[2] + res float64 + ) + + switch op { + case "+", "plus": + op, res = "+", a+b + case "-", "minus": + op, res = "-", a-b + case "*", "times": + op, res = "*", a*b + case "/", "div": + op, res = "/", a/b + case "%", "mod": + res = float64(int(a) % int(b)) + default: + fmt.Println("Please provide a valid operation.") + return + } + + fmt.Printf("%v %v %v = %v\n", a, op, b, res) +} diff --git a/x-tba/foundations/calc/08-funcs/main.go b/x-tba/foundations/calc/08-funcs/main.go new file mode 100644 index 0000000..444e43f --- /dev/null +++ b/x-tba/foundations/calc/08-funcs/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "errors" + "fmt" + "os" + "strconv" +) + +func main() { + // lesson: many - split this + + if len(os.Args) != 4 { + fmt.Println("Usage: calc ") + return + } + + var ( + a, b float64 + err error + ) + + if a, err = parse(os.Args[1]); err != nil { + fmt.Println(err) + return + } + + if b, err = parse(os.Args[3]); err != nil { + fmt.Println(err) + return + } + + op := os.Args[2] + res, err := calc(a, b, op) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%v %s %v = %v\n", a, op, b, res) +} + +func parse(snum string) (n float64, err error) { + n, err = strconv.ParseFloat(snum, 64) + if err != nil { + err = errors.New("Please provide a valid number") + } + return +} + +func calc(a, b float64, op string) (res float64, err error) { + switch op { + case "+", "plus": + op, res = "+", a+b + case "-", "minus": + op, res = "-", a-b + case "*", "times": + op, res = "*", a*b + case "/", "div": + op, res = "/", a/b + case "%", "mod": + res = float64(int(a) % int(b)) + default: + return 0, errors.New("Wrong operation: '" + op + "'") + } + return +} diff --git a/x-tba/foundations/calc/09-packages/calc/calc.go b/x-tba/foundations/calc/09-packages/calc/calc.go new file mode 100644 index 0000000..13197ca --- /dev/null +++ b/x-tba/foundations/calc/09-packages/calc/calc.go @@ -0,0 +1,36 @@ +package calc + +import ( + "errors" + "strconv" +) + +// Parse ... +func Parse(snum string) (n float64, err error) { + n, err = strconv.ParseFloat(snum, 64) + if err != nil { + // Don't loose the actual error for debugging + err = errors.New("Please provide a valid number: " + + err.Error()) + } + return +} + +// Do ... +func Do(a, b float64, op string) (res float64, err error) { + switch op { + case "+", "plus": + op, res = "+", a+b + case "-", "minus": + op, res = "-", a-b + case "*", "times": + op, res = "*", a*b + case "/", "div": + op, res = "/", a/b + case "%", "mod": + res = float64(int(a) % int(b)) + default: + return 0, errors.New("Wrong operation: '" + op + "'") + } + return +} diff --git a/x-tba/foundations/calc/09-packages/main.go b/x-tba/foundations/calc/09-packages/main.go new file mode 100644 index 0000000..b1066a4 --- /dev/null +++ b/x-tba/foundations/calc/09-packages/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "fmt" + "os" + + "github.com/inancgumus/learngo/x-tba/foundations/calc/09-packages/calc" +) + +func main() { + // lesson: packaging + + // separate dependencies like getting and validating + // user data as in here. + // + // we only put calc to another packages, not the other + // stuff. + // + // so, we can reuse the same calc package and use it + // over a web api if we want. + + if len(os.Args) != 4 { + fmt.Println("Usage: calc ") + return + } + + var ( + a, b float64 + err error + ) + + if a, err = calc.Parse(os.Args[1]); err != nil { + fmt.Println(err) + return + } + + if b, err = calc.Parse(os.Args[3]); err != nil { + fmt.Println(err) + return + } + + op := os.Args[2] + res, err := calc.Do(a, b, op) + if err != nil { + fmt.Println(err) + return + } + + fmt.Printf("%v %s %v = %v\n", a, op, b, res) +} diff --git a/x-tba/foundations/calc/calc-scanner/calculations.txt b/x-tba/foundations/calc/calc-scanner/calculations.txt new file mode 100644 index 0000000..178548a --- /dev/null +++ b/x-tba/foundations/calc/calc-scanner/calculations.txt @@ -0,0 +1,4 @@ +4 + 5 +6.5 + 2 +5 - 3 +q diff --git a/x-tba/foundations/calc/calc-scanner/main.go b/x-tba/foundations/calc/calc-scanner/main.go new file mode 100644 index 0000000..2b65a38 --- /dev/null +++ b/x-tba/foundations/calc/calc-scanner/main.go @@ -0,0 +1,66 @@ +/* +go run main.go < ./calculations.txt + +If you're not on Linux or OS X, etc but on Windows, +Then, use Windows PowerShell to do the same thing. +*/ +package main + +import ( + "bufio" + "fmt" + "os" + "strings" +) + +// After functions, you'll see that how we're going to refactor this +// into a more readable version. + +func main() { + const ( + promptChar = "> " + errWrongOp = "%s operation is not supported\n" + errWrongFormat = "operation is not recognized\n" + usage = ` +usage: number operation number +quit : type q to quit +examples: + 3 + 5 + 5 - 3 +` + ) + + fmt.Println(strings.TrimSpace(usage)) + + for s := bufio.NewScanner(os.Stdin); ; { + var ( + a, b, res float64 + op string + ) + + fmt.Print(promptChar, " ") + if !s.Scan() { + break + } + + _, err := fmt.Sscanf(s.Text(), "%f %s %f", &a, &op, &b) + if err != nil { + fmt.Fprintf(os.Stderr, errWrongFormat) + continue + } + + switch op { + case "+": + res = a + b + case "-": + res = a - b + default: + fmt.Printf(errWrongOp, op) + continue + } + + fmt.Printf("%g %s %g = %g\n", a, op, b, res) + } + + fmt.Println("bye.") +}