├── 0_alternate_ways_of_importing_packages ├── alias_package_import.go ├── blank_identifier_import.txt └── dot_package_import.go ├── 1_bubble_sort └── bubble_sort.go ├── 2_garbage_collector_change_in_go13 └── gc_change_example.go ├── 3_gos_pointer_type ├── basic_pointer_arithmetic.go └── pointer_arithmetic.go ├── 4_notes_on_slices ├── copying_slices.go ├── copying_slices_image.jpg ├── incorrect_slice_usage.go ├── slice_example.go └── use_case_problem.go ├── 5_gos_flag_package_creating_a_cli_tool ├── help_flag.go ├── limit_flag.go ├── limit_flag_practical.go ├── limit_flag_with_yes.go ├── parsing_arguments.go ├── usage_without_arguments.go ├── usage_without_arguments_using_flagArgs.go ├── version_flag.go └── yes.go ├── 6_binary_tree └── binaryTreeV1.go ├── 7_gos_time_package_in_a_few_minutes └── main.go ├── 8_randomize_the_elements_of_a_byte_slice_in_one_line ├── README.md ├── iteration.go └── read.go ├── 9_a_better_way_of_handling_stdin ├── README.md ├── example1 │ ├── README.md │ └── main.go ├── example2 │ ├── README.md │ └── main.go └── example3 │ ├── README.md │ └── main.go ├── LICENSE └── README.md /0_alternate_ways_of_importing_packages/alias_package_import.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import format "fmt" 4 | 5 | func main() { 6 | format.Println("Hello, World!") 7 | } -------------------------------------------------------------------------------- /0_alternate_ways_of_importing_packages/blank_identifier_import.txt: -------------------------------------------------------------------------------- 1 | import ( 2 | "image" 3 | _ "image/gif" 4 | _ "image/png" 5 | _ "image/jpeg" 6 | ) -------------------------------------------------------------------------------- /0_alternate_ways_of_importing_packages/dot_package_import.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | . "math" 6 | ) 7 | 8 | func main() { 9 | fmt.Println("Pi is ", Pi) 10 | fmt.Println("The square root of pi is ", SqrtPi) 11 | } 12 | -------------------------------------------------------------------------------- /1_bubble_sort/bubble_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func Sort(slice []int) { 6 | for end := (len(slice) - 1); end >= 0; end-- { 7 | for iteratingSlice := slice; &iteratingSlice[0] != &slice[end]; iteratingSlice = iteratingSlice[1:] { 8 | if iteratingSlice[0] > iteratingSlice[1] { 9 | elementHolder := iteratingSlice[0] 10 | iteratingSlice[0] = iteratingSlice[1] 11 | iteratingSlice[1] = elementHolder 12 | } 13 | } 14 | } 15 | } 16 | 17 | func main() { 18 | numberSlice := []int{1, 4, 6, 8, 7, 9, 3, 5, 2} 19 | 20 | fmt.Printf("\nMain, unsorted integer array: %v\n", numberSlice) 21 | 22 | Sort(numberSlice) 23 | 24 | fmt.Printf("\nMain, sorted integer array: %v\n\n", numberSlice) 25 | } 26 | -------------------------------------------------------------------------------- /2_garbage_collector_change_in_go13/gc_change_example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "unsafe" 7 | ) 8 | 9 | func main() { 10 | var intPtr1, intPtr2 *int 11 | var addressHolder uintptr 12 | 13 | intPtr1 = new(int) 14 | *intPtr1 = 100 15 | 16 | intPtr2 = new(int) 17 | *intPtr2 = 999 18 | 19 | fmt.Printf("\nintPtr1 = %p, dereferenced value = %d\n", intPtr1, *intPtr1) 20 | fmt.Printf("intPtr2 = %p, dereferenced value = %d\n", intPtr2, *intPtr2) 21 | 22 | addressHolder = uintptr(unsafe.Pointer(intPtr1)) 23 | fmt.Printf("\naddressHolder(uintptr) is assigned the integer value of the address %p.\n", unsafe.Pointer(addressHolder)) 24 | 25 | intPtr1 = intPtr2 26 | fmt.Printf("\nintPtr1 is assigned the value of inPtr2, value = %p, dereferenced value = %d\n", intPtr1, *intPtr1) 27 | 28 | fmt.Printf("\nCalling runtime.GC()\n") 29 | runtime.GC() 30 | 31 | fmt.Printf("\naddressHolder(uintptr), value = %p, dereferenced value = %d\n\n", unsafe.Pointer(addressHolder), *(*int)(unsafe.Pointer(addressHolder))) 32 | } 33 | -------------------------------------------------------------------------------- /3_gos_pointer_type/basic_pointer_arithmetic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | intArray := [...]int{1, 2} 10 | 11 | fmt.Printf("\nintArray: %v\n", intArray) 12 | 13 | intPtr := &intArray[0] 14 | fmt.Printf("\nintPtr=%p, *intPtr=%d.\n", intPtr, *intPtr) 15 | 16 | addressHolder := uintptr(unsafe.Pointer(intPtr)) + unsafe.Sizeof(intArray[0]) 17 | 18 | intPtr = (*int)(unsafe.Pointer(addressHolder)) 19 | 20 | fmt.Printf("\nintPtr=%p, *intPtr=%d.\n\n", intPtr, *intPtr) 21 | } 22 | -------------------------------------------------------------------------------- /3_gos_pointer_type/pointer_arithmetic.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | ) 7 | 8 | func main() { 9 | intArray := [...]int{1, 2} 10 | intPtr := &intArray[0] 11 | var addressHolder uintptr 12 | 13 | fmt.Printf("\nintArray:") 14 | for key, value := range intArray { 15 | fmt.Printf("\n[%d] = %d, address %p", key, value, &intArray[key]) 16 | } 17 | 18 | fmt.Printf("\n\nintPtr(*int) is pointing to address %p, dereferenced value %d\n", intPtr, *intPtr) 19 | 20 | // Convert a pointer to an integer to an unsafe.Pointer, then to a uintptr. 21 | addressHolder = uintptr(unsafe.Pointer(intPtr)) 22 | 23 | // Increment the value of the address by the number of bytes of an element which is an integer. 24 | addressHolder = addressHolder + unsafe.Sizeof(intArray[0]) 25 | 26 | // Convert a uintptr to an unsafe.Pointer, then to a pointer to an integer. 27 | intPtr = (*int)(unsafe.Pointer(addressHolder)) 28 | 29 | fmt.Printf("Incremented intPtr by %d bytes, it is now pointing to %p, dereferenced value %d\n\n", unsafe.Sizeof(intArray[0]), intPtr, *intPtr) 30 | } 31 | -------------------------------------------------------------------------------- /4_notes_on_slices/copying_slices.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | intSlice := []int{1, 2, 3} 7 | 8 | secondIntSlice := intSlice 9 | fmt.Printf("\nintSlice:%v\n", intSlice) 10 | 11 | secondIntSlice[0] = 9 12 | fmt.Printf("\nsecondIntSlice[0] = 9.\n") 13 | fmt.Printf("\nsecondIntSlice:%v\n", intSlice) 14 | 15 | fmt.Printf("\nintSlice:%v\n", intSlice) 16 | 17 | secondIntSlice = secondIntSlice[0:1] 18 | fmt.Printf("\nsliced secondIntSlice to [0,1].\n") 19 | fmt.Printf("\nsecondIntSlice:%v\n", secondIntSlice) 20 | 21 | fmt.Printf("\nintSlice - len:%v cap:%v\n", len(intSlice), cap(intSlice)) 22 | fmt.Printf("\nsecondIntSlice - len:%v cap:%v\n\n", len(secondIntSlice), cap(secondIntSlice)) 23 | } 24 | -------------------------------------------------------------------------------- /4_notes_on_slices/copying_slices_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xercoy/learn-go-with-me/186b2bd363ccb01746114a9c9ce10074089f3472/4_notes_on_slices/copying_slices_image.jpg -------------------------------------------------------------------------------- /4_notes_on_slices/incorrect_slice_usage.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func intSliceHandler(intSlice []int, newValue int) { 6 | intSlice = make([]int, 1) 7 | intSlice[0] = newValue 8 | 9 | fmt.Printf("\nintSliceHandler - intSlice:%v\n", intSlice) 10 | } 11 | 12 | func main() { 13 | var intSlice []int 14 | 15 | fmt.Printf("\nmain - intSlice:%v\n", intSlice) 16 | 17 | intSliceHandler(intSlice, 5) 18 | 19 | fmt.Printf("\nmain - intSlice after intSliceHandler():%v\n\n", intSlice) 20 | } 21 | -------------------------------------------------------------------------------- /4_notes_on_slices/slice_example.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func intSliceHandler(intSlice []int, newValue int) []int { 6 | return append(intSlice, newValue) 7 | } 8 | 9 | func main() { 10 | var intSlice []int 11 | 12 | fmt.Printf("\nmain - intSlice:%v\n", intSlice) 13 | 14 | intSlice = intSliceHandler(intSlice, 5) 15 | 16 | fmt.Printf("\nmain - intSlice after intSliceHandler():%v\n\n", intSlice) 17 | } 18 | -------------------------------------------------------------------------------- /4_notes_on_slices/use_case_problem.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type Foo struct { 6 | intSlice []int 7 | } 8 | 9 | func Fill(f Foo, newValue int) { 10 | fmt.Printf("\nFill - Executing append(f.intSlice, newValue)") 11 | f.intSlice = append(f.intSlice, newValue) 12 | 13 | fmt.Printf("\nFill - f.intSlice:%v", f.intSlice) 14 | } 15 | 16 | func main() { 17 | var FooVariable Foo 18 | 19 | fmt.Printf("\nmain - FooVariable.intSlice:%v", FooVariable.intSlice) 20 | 21 | fmt.Printf("\nmain - Executing Fill(FooVariable, 12)") 22 | Fill(FooVariable, 12) 23 | 24 | fmt.Printf("\nmain - FooVariable.intSlice:%v\n\n", FooVariable.intSlice) 25 | } -------------------------------------------------------------------------------- /5_gos_flag_package_creating_a_cli_tool/help_flag.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | 11 | var help bool 12 | 13 | var helpText = ` 14 | Usage: 15 | 16 | --help displays usage information 17 | 18 | --version displays utility version 19 | 20 | --limit specifies number of times arguments will be 21 | be displayed. 22 | ` 23 | 24 | flag.BoolVar(&help, "help", false, helpText) 25 | 26 | flag.Parse() 27 | 28 | if help { 29 | fmt.Printf("%s\n", flag.Lookup("help").Usage) 30 | os.Exit(0) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /5_gos_flag_package_creating_a_cli_tool/limit_flag.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | "flag" 6 | "strconv" 7 | ) 8 | 9 | type CustomStruct struct { 10 | FlagValue int 11 | } 12 | 13 | func (cF *CustomStruct) String() string { 14 | return strconv.Itoa(cF.FlagValue) 15 | } 16 | 17 | func (cF *CustomStruct) Set(s string) error { 18 | cF.FlagValue, _ = strconv.Atoi(s) 19 | 20 | return nil 21 | } 22 | 23 | func (cF *CustomStruct) Get() int { 24 | return cF.FlagValue 25 | } 26 | 27 | func (cF *CustomStruct) IsSet() bool { 28 | if cF.FlagValue == -1 { 29 | return false 30 | } 31 | 32 | return true 33 | } 34 | 35 | func main() { 36 | limitFlag := CustomStruct{-1} 37 | 38 | flag.Var(&limitFlag, "limit", "Limits output") 39 | 40 | flag.Parse() 41 | 42 | if limitFlag.IsSet() { 43 | fmt.Printf("\nLimit: %d\n\n", limitFlag.Get()) 44 | } else { 45 | fmt.Printf("\nLimit flag not included.\n\n") 46 | } 47 | } -------------------------------------------------------------------------------- /5_gos_flag_package_creating_a_cli_tool/limit_flag_practical.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | "flag" 6 | "strconv" 7 | "errors" 8 | ) 9 | 10 | type customFlag struct { 11 | FlagValue int 12 | } 13 | 14 | func (cF *customFlag) String() string { 15 | return strconv.Itoa(cF.FlagValue) 16 | } 17 | 18 | func (cF *customFlag) Set(s string) error { 19 | convertedArg, _ := strconv.Atoi(s) 20 | 21 | if (convertedArg < 0) { 22 | return errors.New("Argument value for limit flag invalid. Must be greater than or equal to 0.") 23 | } 24 | 25 | cF.FlagValue = convertedArg 26 | 27 | return nil 28 | } 29 | 30 | func (cF *customFlag) Get() int { 31 | return cF.FlagValue 32 | } 33 | 34 | func main() { 35 | limit := customFlag{-1} 36 | 37 | flag.Var(&limit, "limit", "Limits the number of times arguments should be displayed. Infinity otherwise.") 38 | 39 | flag.Parse() 40 | 41 | if limit.Get() == -1 { 42 | for true { 43 | fmt.Printf("y \n") 44 | } 45 | } else { 46 | for i := 0; i < limit.Get(); i++ { 47 | fmt.Printf("y \n") 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /5_gos_flag_package_creating_a_cli_tool/limit_flag_with_yes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | "flag" 6 | "strconv" 7 | "errors" 8 | ) 9 | 10 | type customFlag struct { 11 | FlagValue int 12 | } 13 | 14 | func (cF *customFlag) String() string { 15 | return strconv.Itoa(cF.FlagValue) 16 | } 17 | 18 | func (cF *customFlag) Set(s string) error { 19 | convertedArg, _ := strconv.Atoi(s) 20 | 21 | if (convertedArg < 0) { 22 | return errors.New("Argument value for limit flag invalid. Must be greater than or equal to 0.") 23 | } 24 | 25 | cF.FlagValue = convertedArg 26 | 27 | return nil 28 | } 29 | 30 | func (cF *customFlag) Get() int { 31 | return cF.FlagValue 32 | } 33 | 34 | func main() { 35 | limit := customFlag{-1} 36 | 37 | flag.Var(&limit, "limit", "Limits the number of times arguments should be displayed. Infinity otherwise.") 38 | 39 | flag.Parse() 40 | 41 | if limit.Get() == -1 { 42 | for true { 43 | fmt.Printf("y \n") 44 | } 45 | } else { 46 | for i := 0; i < limit.Get(); i++ { 47 | fmt.Printf("y \n") 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /5_gos_flag_package_creating_a_cli_tool/parsing_arguments.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | 10 | for _, argument := range flag.Args() { 11 | fmt.Printf("\n%s", argument) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /5_gos_flag_package_creating_a_cli_tool/usage_without_arguments.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | for true { 10 | if len(os.Args) == 1 { 11 | fmt.Printf("y \n") 12 | } else { 13 | break; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /5_gos_flag_package_creating_a_cli_tool/usage_without_arguments_using_flagArgs.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | flag.Parse() 10 | 11 | for true { 12 | if len(flag.Args()) == 0 { 13 | fmt.Printf("y \n") 14 | } else { 15 | break 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /5_gos_flag_package_creating_a_cli_tool/version_flag.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | var version *bool 11 | version = flag.Bool("version", false, "1.0") 12 | 13 | flag.Parse() 14 | 15 | if *version { 16 | fmt.Printf("Version %s\n", flag.Lookup("version").Usage) 17 | os.Exit(0) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /5_gos_flag_package_creating_a_cli_tool/yes.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "strconv" 7 | ) 8 | 9 | var ( 10 | versionUsageText = "0.1" 11 | helpUsageText = ` 12 | Usage: yes [FLAGS] [ARGUMENTS] 13 | 14 | --help displays usage information 15 | 16 | --version displays utility version 17 | 18 | --limit specifies number of times 19 | arguments will be 20 | displayed. Value must be 21 | 0 or greater. 22 | 23 | Note: flags must be specified before arguments. 24 | ` 25 | 26 | limitUsageText = "0 or greater integer value, determines times output is displayed" 27 | ) 28 | 29 | type customFlag struct { 30 | Value int 31 | } 32 | 33 | func (cF *customFlag) Set(s string) error { 34 | cF.Value, _ = strconv.Atoi(s) 35 | return nil 36 | } 37 | 38 | func (cF *customFlag) Get() int { 39 | return cF.Value 40 | } 41 | 42 | func (cF *customFlag) String() string { 43 | return strconv.Itoa(cF.Value) 44 | } 45 | 46 | func (cF *customFlag) IsSet() bool { 47 | if cF.Value == -1 { 48 | return false 49 | } 50 | 51 | return true 52 | } 53 | 54 | func main() { 55 | versionFlagPtr := flag.Bool("version", false, versionUsageText) 56 | 57 | var helpFlagValue bool 58 | flag.BoolVar(&helpFlagValue, "help", false, helpUsageText) 59 | 60 | //-1 is the default value, see the IsSet method. 61 | limitFlagCustom := customFlag{-1} 62 | flag.Var(&limitFlagCustom, "limit", limitUsageText) 63 | 64 | var outputString string 65 | 66 | flag.Parse() 67 | 68 | // Remember, this needs to be executed after flag.Parse() 69 | argCount := len(flag.Args()) 70 | 71 | // Append arguments together to make output string 72 | for _, argument := range flag.Args() { 73 | outputString += argument + " " 74 | } 75 | 76 | switch { 77 | 78 | // Version Flag 79 | case *versionFlagPtr: 80 | { 81 | fmt.Printf("Version: %s\n", flag.Lookup("version").Usage) 82 | break 83 | } 84 | 85 | //Help Flag 86 | case helpFlagValue: 87 | { 88 | fmt.Printf("%s\n", flag.Lookup("help").Usage) 89 | break 90 | } 91 | 92 | //Limit Flag 93 | case limitFlagCustom.IsSet() == true: 94 | { 95 | //Limit flag set w.o any arguments, print y limited times 96 | if argCount == 0 { 97 | for i := 0; i < limitFlagCustom.Get(); i++ { 98 | fmt.Printf("y \n") 99 | } 100 | 101 | // Limit flag set with arguments, print outputString limited times 102 | } else { 103 | for i := 0; i < limitFlagCustom.Get(); i++ { 104 | fmt.Printf("%s\n", outputString) 105 | } 106 | } 107 | 108 | break 109 | } 110 | 111 | //Default, no flags specified. 112 | case true: 113 | { 114 | // Default without any arguments 115 | if argCount == 0 { 116 | for true { 117 | fmt.Printf("y \n") 118 | } 119 | 120 | // Default with arguments 121 | } else { 122 | for true { 123 | fmt.Printf("%s\n", outputString) 124 | } 125 | } 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /6_binary_tree/binaryTreeV1.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func newNode() *Node { 8 | n := &Node{} 9 | return n 10 | } 11 | 12 | func (n *Node) Insert(newValue interface{}) error { 13 | switch { 14 | case n.Data == nil: 15 | { 16 | n.Data = newValue 17 | } 18 | 19 | case newValue.(int) < (n.Data).(int): 20 | { 21 | if n.Left == nil { 22 | n.Left = newNode() 23 | n.Left.Data = newValue 24 | } else { 25 | return n.Left.Insert(newValue) 26 | } 27 | } 28 | 29 | case newValue.(int) > (n.Data).(int): 30 | { 31 | if n.Right == nil { 32 | n.Right = newNode() 33 | n.Right.Data = newValue 34 | } else { 35 | return n.Right.Insert(newValue) 36 | } 37 | 38 | } 39 | } 40 | 41 | return nil 42 | } 43 | 44 | func (n *Node) Find(value interface{}) *Node { 45 | 46 | if n.Data == nil { 47 | return nil 48 | } 49 | 50 | switch { 51 | case n.Data == value: 52 | { 53 | return n 54 | } 55 | 56 | case value.(int) < n.Data.(int): 57 | { 58 | if n.Left == nil { 59 | break 60 | } 61 | return n.Left.Find(value) 62 | } 63 | 64 | case value.(int) > n.Data.(int): 65 | { 66 | if n.Right == nil { 67 | break 68 | } 69 | return n.Right.Find(value) 70 | 71 | } 72 | } 73 | return nil 74 | } 75 | 76 | func (n *Node) Print() { 77 | if n == nil { 78 | return 79 | } 80 | 81 | fmt.Printf("%v ", n.Data) 82 | 83 | (n.Left).Print() 84 | (n.Right).Print() 85 | } 86 | 87 | func max(num1 int, num2 int) int { 88 | if num1 > num2 { 89 | return num1 90 | } 91 | 92 | return num2 93 | } 94 | 95 | func min(num1 int, num2 int) int { 96 | if num1 > num2 { 97 | return num2 98 | } 99 | 100 | return num1 101 | } 102 | 103 | func (n *Node) Height() int { 104 | var leftHeight, rightHeight int 105 | 106 | if n.Left != nil { 107 | leftHeight = n.Left.Height() 108 | } 109 | 110 | if n.Right != nil { 111 | rightHeight = n.Right.Height() 112 | } 113 | 114 | return 1 + max(leftHeight, rightHeight) 115 | } 116 | 117 | type Node struct { 118 | Left *Node 119 | Right *Node 120 | Data interface{} 121 | } 122 | 123 | func (n *Node) FindMax() int { 124 | if n.Right == nil { 125 | return n.Data.(int) 126 | } 127 | 128 | return max(n.Data.(int), n.Right.FindMax()) 129 | } 130 | 131 | func (n *Node) HasTwoChildren() bool { 132 | if n.Left != nil { 133 | if n.Right != nil { 134 | return true 135 | } 136 | } 137 | 138 | return false 139 | } 140 | 141 | func (n *Node) HasNoChildren() bool { 142 | if n.Left == nil { 143 | if n.Right == nil { 144 | return true 145 | } 146 | } 147 | 148 | return false 149 | } 150 | 151 | func (n *Node) HasLeftChild() bool { 152 | if n.Left != nil { 153 | return true 154 | } 155 | 156 | return false 157 | } 158 | 159 | func (n *Node) HasRightChild() bool { 160 | if n.Right != nil { 161 | return true 162 | } 163 | 164 | return false 165 | } 166 | 167 | func (n *Node) FindMin() int { 168 | if n.Left == nil { 169 | return n.Data.(int) 170 | } 171 | 172 | return min(n.Data.(int), n.Left.FindMin()) 173 | } 174 | 175 | func (n *Node) IsEmpty() bool { 176 | if n.Data == nil { 177 | return true 178 | } 179 | 180 | return false 181 | } 182 | 183 | func (n *Node) Delete(value interface{}) *Node { 184 | 185 | if n.Data == nil { 186 | return nil 187 | } 188 | 189 | switch { 190 | case value.(int) < n.Data.(int): 191 | { 192 | if n.Left == nil { 193 | return nil 194 | } 195 | 196 | if n.Left.Data.(int) == value.(int) { 197 | n.Left = n.Left.Delete(value) 198 | } else { 199 | n.Left.Delete(value) 200 | } 201 | } 202 | 203 | case value.(int) > n.Data.(int): 204 | { 205 | if n.Right == nil { 206 | return nil 207 | } 208 | 209 | if n.Right.Data.(int) == value.(int) { 210 | n.Right = n.Right.Delete(value) 211 | } else { 212 | n.Right.Delete(value) 213 | } 214 | } 215 | 216 | case value.(int) == n.Data: 217 | { 218 | switch { 219 | 220 | case n.HasNoChildren(): 221 | { 222 | n.Data = nil 223 | return nil 224 | } 225 | 226 | case n.HasLeftChild() || n.HasTwoChildren(): 227 | { 228 | n.Data = n.Left.FindMax() 229 | n.Left = n.Left.Delete(n.Data) 230 | } 231 | 232 | case n.HasRightChild(): 233 | { 234 | n.Data = n.Right.FindMin() 235 | n.Right = n.Right.Delete(n.Data) 236 | } 237 | 238 | } 239 | 240 | } 241 | 242 | } 243 | 244 | return n 245 | } 246 | 247 | func main() { 248 | var bTree Node 249 | 250 | bTree.Insert(10) 251 | bTree.Insert(2) 252 | bTree.Insert(18) 253 | bTree.Insert(39) 254 | bTree.Insert(41) 255 | bTree.Insert(4) 256 | bTree.Insert(1) 257 | bTree.Insert(40) 258 | 259 | fmt.Printf("\nPrinted Tree Values:\n") 260 | bTree.Print() 261 | 262 | 263 | fmt.Printf("\n\nTesting Find()") 264 | 265 | fmt.Printf("\nAttempting to Find 180: ") 266 | if bTree.Find(180) != nil { 267 | fmt.Printf("FOUND\n") 268 | } else { 269 | fmt.Printf("NOT FOUND\n") 270 | } 271 | 272 | fmt.Printf("Attempting to Find 4: ") 273 | if bTree.Find(4) != nil { 274 | fmt.Printf("FOUND\n") 275 | } else { 276 | fmt.Printf("NOT FOUND\n") 277 | } 278 | 279 | fmt.Printf("\nThe height of the current tree is %d.\n\n", bTree.Height()) 280 | 281 | fmt.Printf("Testing Delete() on Node without children:\n") 282 | fmt.Printf("Removing 1...") 283 | bTree.Delete(1) 284 | fmt.Printf("\nPrinted Tree Values:\n") 285 | bTree.Print() 286 | 287 | fmt.Printf("\n\nTesting Delete() on Node with one right child:\n") 288 | fmt.Printf("Removing 4...") 289 | bTree.Delete(4) 290 | fmt.Printf("\nPrinted Tree Values:\n") 291 | bTree.Print() 292 | 293 | fmt.Printf("\n\nTesting Delete() on Node with one left child:\n") 294 | fmt.Printf("Removing 40...") 295 | bTree.Delete(40) 296 | fmt.Printf("\nPrinted Tree Values:\n") 297 | bTree.Print() 298 | 299 | fmt.Printf("\n\nTesting Delete() on Node with two children:\n") 300 | fmt.Printf("Removing 10...") 301 | bTree.Delete(10) 302 | fmt.Printf("\nPrinted Tree Values:\n") 303 | bTree.Print() 304 | 305 | fmt.Printf("\n\nTesting Delete() on a Node with a nonexisting value:\n") 306 | fmt.Printf("Removing 49...") 307 | bTree.Delete(49) 308 | fmt.Printf("\nPrinted Tree Values:\n") 309 | bTree.Print() 310 | 311 | fmt.Printf("\n\nRemoving 18...") 312 | bTree.Delete(18) 313 | fmt.Printf("\nPrinted Tree Values:\n") 314 | bTree.Print() 315 | 316 | fmt.Printf("\n\nRemoving 41...") 317 | bTree.Delete(41) 318 | fmt.Printf("\nPrinted Tree Values:\n") 319 | bTree.Print() 320 | 321 | fmt.Printf("\n\nRemoving 2...") 322 | bTree.Delete(2) 323 | fmt.Printf("\nPrinted Tree Values:\n") 324 | bTree.Print() 325 | 326 | if bTree.IsEmpty() { 327 | fmt.Printf("\n\nbTree is empty.") 328 | } else { 329 | fmt.Printf("\n\nbTree is not empty.") 330 | } 331 | 332 | fmt.Printf("\n\nTesting to Delete() on last node") 333 | fmt.Printf("\nRemoving 39...") 334 | bTree.Delete(39) 335 | fmt.Printf("\nPrinted Tree Values:\n") 336 | bTree.Print() 337 | 338 | if bTree.IsEmpty() { 339 | fmt.Printf("\n\nbTree is empty.") 340 | } else { 341 | fmt.Printf("\n\nbTree is not empty.") 342 | } 343 | 344 | fmt.Printf("\n\n") 345 | } 346 | -------------------------------------------------------------------------------- /7_gos_time_package_in_a_few_minutes/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | RunAllExamples() 11 | fmt.Printf("\n\n") 12 | } 13 | 14 | func RunAllExamples() { 15 | // Create times. 16 | Example1() 17 | Example2() 18 | Example3() 19 | Example4() 20 | Example5() 21 | Example6() 22 | } 23 | 24 | func Example1() { 25 | var ( 26 | t1, t2, t3 time.Time 27 | err error 28 | estLoc, utcLoc *time.Location 29 | ) 30 | 31 | estLoc, err = time.LoadLocation("EST") 32 | if err != nil { 33 | log.Fatalln(err) 34 | } 35 | 36 | utcLoc, err = time.LoadLocation("UTC") 37 | if err != nil { 38 | log.Fatalln(err) 39 | } 40 | 41 | //Time format, string to interpret format on, and a *time.Location 42 | t1, err = time.ParseInLocation(time.Kitchen, "6:03PM", estLoc) 43 | if err != nil { 44 | log.Fatalln(err) 45 | } 46 | 47 | // Return a time.Time object based on current environment settings. 48 | t2 = time.Now() 49 | 50 | /* year int, month Month, day, hour, 51 | min, sec, nsec int, loc *Location) Time */ 52 | t3 = time.Date(200, 4, 1, 0, 4, 0, 3, utcLoc) 53 | 54 | fmt.Printf("\n====EXAMPLE 1====") 55 | fmt.Printf("\nCreating times in three different ways.") 56 | 57 | fmt.Printf("\nt1 = %s \nt2 = %s \nt3 = %s", 58 | t1.String(), t2.String(), t3.String()) 59 | } 60 | 61 | func Example2() { 62 | var ( 63 | t1, t2, t3 time.Time 64 | err error 65 | estLoc, utcLoc *time.Location 66 | ) 67 | 68 | estLoc, err = time.LoadLocation("EST") 69 | if err != nil { 70 | log.Fatalln(err) 71 | } 72 | 73 | utcLoc, err = time.LoadLocation("UTC") 74 | if err != nil { 75 | log.Fatalln(err) 76 | } 77 | 78 | t1, err = time.ParseInLocation(time.Kitchen, "6:03PM", estLoc) 79 | if err != nil { 80 | log.Fatalln(err) 81 | } 82 | 83 | t2, err = time.ParseInLocation(time.Kitchen, "11:03PM", utcLoc) 84 | 85 | fmt.Printf("\n\n====EXAMPLE 2====") 86 | fmt.Printf("\nComparing two times.") 87 | 88 | fmt.Printf("\nt1 = %v \nt2 = %v", 89 | t1.String(), t3.String()) 90 | 91 | if t1 == t2 { 92 | fmt.Printf("\nt1 and t2 are equal using `==`.") 93 | } else { 94 | fmt.Printf("\nt1 and t2 are not equal using `==`.") 95 | } 96 | 97 | if t1.Equal(t2) { 98 | fmt.Printf("\nt1 and t2 are equal using the Equal method.") 99 | } else { 100 | fmt.Printf("\nt1 and t2 are not equal using the Equal method.") 101 | } 102 | 103 | return 104 | } 105 | 106 | // Comparing whether two dates occur before or after each other. 107 | func Example3() { 108 | var ( 109 | t1, t2 time.Time 110 | ) 111 | 112 | // Get current time and date information. 113 | t1 = time.Now() 114 | 115 | // assign t2 to the current time and date information + 1 day. 116 | t2 = t1.Add(time.Duration(24) * time.Hour) 117 | 118 | fmt.Printf("\n\n====EXAMPLE 3====") 119 | fmt.Printf("\nComparing one time occuring before or after another.") 120 | 121 | if t1.After(t2) { 122 | fmt.Printf("\nt1(%s) occurs after t2(%s)", 123 | t1.String(), t2.String()) 124 | } else { 125 | fmt.Printf("\nt1(%s) occurs before t2(%s)", 126 | t1.String(), t2.String()) 127 | } 128 | } 129 | 130 | // Representing a time in different formats. 131 | func Example4() { 132 | var ( 133 | t1 time.Time 134 | err error 135 | estLoc *time.Location 136 | ) 137 | 138 | estLoc, err = time.LoadLocation("EST") 139 | if err != nil { 140 | log.Fatalln(err) 141 | } 142 | 143 | fmt.Printf("\n\n====EXAMPLE 4====") 144 | fmt.Printf("\nRepresenting time in different formats.") 145 | 146 | t1, err = time.ParseInLocation(time.RFC1123, 147 | "Fri, 25 Dec 2015 12:00:00 EST", 148 | estLoc) 149 | 150 | fmt.Printf("\nt1 has been set to Xmas day 2015 Eastern Time.") 151 | fmt.Printf("\nt1 in RFC3339: %s", t1.Format(time.RFC3339)) 152 | fmt.Printf("\nt1 in RFC1123: %s", t1.Format(time.RFC1123)) 153 | 154 | fmt.Printf("\nt1 in custom format: %v %v %v, %v", 155 | t1.Weekday().String(), t1.Month().String(), 156 | t1.Day(), t1.Year()) 157 | } 158 | 159 | // Representing a time from one place to another. 160 | func Example5() { 161 | var ( 162 | t1 time.Time 163 | err error 164 | estLoc *time.Location 165 | ) 166 | 167 | estLoc, _ = time.LoadLocation("EST") 168 | 169 | fmt.Printf("\n\n====EXAMPLE 5====") 170 | fmt.Printf("\nRepresenting equivalent times in different time zones.") 171 | 172 | t1, err = time.ParseInLocation(time.RFC1123, 173 | "Fri, 25 Dec 2015 12:00:00 EST", 174 | estLoc) 175 | if err != nil { 176 | log.Fatalln(err) 177 | } 178 | 179 | fmt.Printf("\nt1 (set to Xmas 2015 EST at noon): %s", 180 | t1.String()) 181 | 182 | londonLoc, err := time.LoadLocation("Europe/London") 183 | if err != nil { 184 | log.Fatalln(err) 185 | } 186 | fmt.Printf("\nt1 equivalent time in London: %s", 187 | t1.In(londonLoc).String()) 188 | } 189 | 190 | func Example6() { 191 | var ( 192 | t1, t2 time.Time 193 | ) 194 | 195 | fmt.Printf("\n\n====Example 6====") 196 | fmt.Printf("\nTiming Code") 197 | 198 | t1 = time.Now() 199 | 200 | time.Sleep(time.Duration(3) * time.Second) 201 | 202 | t2 = time.Now() 203 | 204 | tDifference := t2.Sub(t1) 205 | fmt.Printf("\nThe sleep was %s long", tDifference.String()) 206 | 207 | //Alternative 208 | fmt.Printf("\nPerforming example once more using the Since method.") 209 | t1 = time.Now() 210 | 211 | time.Sleep(time.Duration(3) * time.Second) 212 | fmt.Printf("\nThe sleep was %s long.", time.Since(t1).String()) 213 | } 214 | -------------------------------------------------------------------------------- /8_randomize_the_elements_of_a_byte_slice_in_one_line/README.md: -------------------------------------------------------------------------------- 1 | Randomize the Elements of a Byte Slice in One Line - Code 2 | 3 | View the blog post [here](http://learngowith.me/randomize-the-elements-of-a-byte-slice-in-one-line/) 4 | 5 | #### Usage 6 | 7 | Run the code sample that randomizes a slice via iteration: `$go run iteration.go` 8 | 9 | Sample Output 10 | ``` 11 | 5.08µs - created random slice [217 235 99 200 69 241 191 174 64 73 217 126 38 114 81 54 151 212 188 1 187 97 174 165 243 37 191 2 211 249 172 176 68 159 55 98 81 55 55 85 156 22 97 204 123 161 115 121 102 96 23 24 105 131 168 141 166 80 56 238 17 96 38 195 218 25 173 169 205 235 26 229 186 178 199 194 131 159 144 34 25 218 147 9 20 193 41 11 67 43 156 235 40 10 109 90 64 110 83 244] 12 | ``` 13 | 14 | === 15 | 16 | Run the code sample that randomizes a slice via the new `Read()` function: `$go run read.go` 17 | 18 | Sample Output 19 | ``` 20 | 1.188µs - created random slice [90 53 181 49 162 205 104 37 192 171 174 192 41 224 35 115 223 112 87 129 84 69 248 171 144 211 83 177 233 215 154 208 132 203 44 216 146 197 59 141 179 245 4 128 105 48 146 205 159 216 157 149 45 49 112 255 237 1 158 29 254 204 171 120 226 44 96 68 182 12 208 153 97 71 204 178 246 156 70 69 58 97 233 123 140 95 179 77 226 177 87 142 182 174 184 193 164 123 223 220] 21 | ``` -------------------------------------------------------------------------------- /8_randomize_the_elements_of_a_byte_slice_in_one_line/iteration.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | // Set a seed for the current time in milliseconds. 11 | // Ensures random values on every run. 12 | rand.Seed(time.Now().UnixNano()) 13 | 14 | randomByteSlice := make([]byte, 100) 15 | 16 | // Start timer 17 | startTime := time.Now() 18 | 19 | for index, _ := range randomByteSlice { 20 | randomByteSlice[index] = byte(rand.Int()) 21 | } 22 | 23 | // Retrieve total run time 24 | endTime := time.Now().Sub(startTime) 25 | 26 | fmt.Printf("%s - created random slice %v", 27 | endTime.String(), randomByteSlice) 28 | } 29 | -------------------------------------------------------------------------------- /8_randomize_the_elements_of_a_byte_slice_in_one_line/read.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | // Set a seed for the current time in milliseconds. 11 | // Ensures random values on every run. 12 | rand.Seed(time.Now().UnixNano()) 13 | 14 | randomByteSlice := make([]byte, 100) 15 | 16 | // Start timer 17 | startTime := time.Now() 18 | 19 | rand.Read(randomByteSlice) 20 | 21 | // Retrieve total run time 22 | endTime := time.Now().Sub(startTime) 23 | 24 | fmt.Printf("%s - created random slice %v", 25 | endTime.String(), randomByteSlice) 26 | } 27 | -------------------------------------------------------------------------------- /9_a_better_way_of_handling_stdin/README.md: -------------------------------------------------------------------------------- 1 | # A better way of handling stdin 2 | 3 | I usually pipe content to programs that depend on some kind of input from `stdin`. Annoyingly enough, when running the program manually and forgetting to pipe content, it hangs. 4 | 5 | To get past this, I'll `Ctrl-c` and correct the command. In terms of automatically handling this, I would skip relevant code by setting a flag. Simple, right? 6 | 7 | What if I could have my code detect when nothing is piped to `stdin` and properly handle both situations? This would drastically reduce the likelihood of both human and automated error, not to mention increase code quality. 8 | 9 | The key to this whole blog post is determining the file mode of `stdin` which is represented by the [`os.FileMode`](https://golang.org/src/os/types.go?s=1044:1064#L20) type. The next two lines of code are very useful: 10 | 11 | ``` 12 | // Retrieve file information of stdin (os.FileInfo) 13 | stdinFileInfo, _ := os.Stdin.Stat() 14 | 15 | // Print string representation of stdin's file mode. 16 | fmt.Println(stdinFileInfo.Mode().String()) 17 | ``` 18 | 19 | If we print the string representation of `stdin`'s file mode without piping anything, we get: 20 | ``` 21 | Dcrw--w---- 22 | ``` 23 | the notation of the file mode, `Dc`, describes two things: `D`, that the file is a device, and more specifically, `c`, that the device is a character device. The remaining characters represent the file's permission bits. 24 | 25 | Now, if we observe the file mode of `stdin` when content is being piped, we get: 26 | ``` 27 | prw-rw---- 28 | ``` 29 | this time, the file mode describes a pipe, denoted by `p`. 30 | 31 | View the example in the repo [here](https://github.com/Xercoy/learn-go-with-me/tree/master/be_smart_with_stdin/example1). 32 | 33 | ######The Hard Work is Done 34 | 35 | We could identify the the two distinct file modes by performing a binary AND operation against constants defined in the `os` package which represent them (view them [here](https://golang.org/pkg/os/#FileMode)). The constants can be used as a mask to determine which file mode is present. 36 | 37 | For pipes (true): 38 | ``` 39 | // File Mode of os.Stdin : prw-rw---- 40 | // os.ModeNamedPipe : p--------- 41 | // Binary AND Result : p--------- 42 | 43 | if (stdinFileInfo.Mode() & os.ModeNamedPipe != 0) { 44 | fmt.Printf("Input From Pipe!") 45 | } 46 | ``` 47 | 48 | Without piped content (true): 49 | ``` 50 | //File Mode of os.Stdin : Dcrw--w---- 51 | //os.ModeCharDevice : c--------- 52 | //Binary AND Result : c--------- 53 | 54 | if (stdinFileInfo.Mode() & os.ModeCharDevice != 0) { 55 | fmt.Printf("Input From Terminal!") 56 | } 57 | ``` 58 | 59 | Run the example via [playground](https://play.golang.org/p/Jk_8UoKLhX) (hardcoded to not have content piped) or view it in the [repo](https://github.com/Xercoy/learn-go-with-me/tree/master/be_smart_with_stdin/example2). 60 | 61 | ######In Practice 62 | 63 | The ability to identify when content is being piped gives rightful control back to the developer who can handle each situation accordingly. 64 | 65 | This simplified example will output a greeting with a random name if one isn't provided via `stdin`. Run the full, more detailed example via [playground](https://play.golang.org/p/G5jI8s9LCd) or view it in the [repo](https://github.com/Xercoy/learn-go-with-me/tree/master/be_smart_with_stdin/example3). Note that the [randomization in playground isn't possible](https://blog.golang.org/playground). 66 | ``` 67 | var name string 68 | 69 | // Get a name from stdin if possible 70 | if (stdinFileInfo.Mode() & os.ModeNamedPipe != 0) { 71 | 72 | stdinContent, _ := ioutil.ReadAll(os.Stdin) 73 | name = string(stdinContent) 74 | } else { 75 | 76 | defaultNames := []string{"user","creeper"} 77 | 78 | // Pseudorandom magic 79 | rand.Seed(time.Now().UnixNano()) 80 | randomIndex := rand.Intn(len(defaultNames)) 81 | 82 | name = defaultNames[randomIndex] 83 | } 84 | 85 | fmt.Printf("Hello, %s!", name) 86 | ``` 87 | 88 | ###### With piped content: 89 | ``` 90 | $ printf "Corey" | go run main.go 91 | > Hello, Corey! 92 | ``` 93 | 94 | ###### Without piped content: 95 | ``` 96 | $ go run main.go 97 | > Hello, creeper! 98 | ``` 99 | 100 | Feel free to improve or correct any content, or head to the [repo](https://github.com/Xercoy/learn-go-with-me) to open an issue and suggest a topic. Happy coding! -------------------------------------------------------------------------------- /9_a_better_way_of_handling_stdin/example1/README.md: -------------------------------------------------------------------------------- 1 | Command: 2 | ``` 3 | go run main.go 4 | ``` 5 | 6 | Output: 7 | ``` 8 | 2016/07/13 20:07:57 os.Stdin File Mode : Dcrw--w---- 9 | ``` 10 | 11 | --- 12 | 13 | Command: 14 | ``` 15 | echo "foobar" | go run main.go 16 | ``` 17 | 18 | Output: 19 | ``` 20 | 2016/07/13 20:08:24 os.Stdin File Mode : prw-rw---- 21 | ``` -------------------------------------------------------------------------------- /9_a_better_way_of_handling_stdin/example1/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | stdinFileInfo, _ := os.Stdin.Stat() 10 | log.Printf("os.Stdin File Mode : %s", stdinFileInfo.Mode().String()) 11 | } 12 | -------------------------------------------------------------------------------- /9_a_better_way_of_handling_stdin/example2/README.md: -------------------------------------------------------------------------------- 1 | Command: 2 | ``` 3 | go run main.go 4 | ``` 5 | 6 | Output: 7 | ``` 8 | 2016/07/13 19:52:49 File Info Mode of os.Stdin : Dcrw--w---- 9 | 2016/07/13 19:52:49 os.ModeCharDevice : c--------- 10 | 2016/07/13 19:52:49 Binary AND Result : c--------- 11 | Input from Terminal 12 | ``` 13 | 14 | --- 15 | 16 | Command: 17 | ``` 18 | echo "foobar" | go run main.go 19 | ``` 20 | 21 | Output: 22 | ``` 23 | 2016/07/13 19:48:24 File Info Mode of os.Stdin : prw-rw---- 24 | 2016/07/13 19:48:24 os.ModeNamedPipe : p--------- 25 | 2016/07/13 19:48:24 Binary AND Result : p--------- 26 | Input from Pipe 27 | ``` -------------------------------------------------------------------------------- /9_a_better_way_of_handling_stdin/example2/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | ) 8 | 9 | func main() { 10 | // Stat returns file info structure describing the file. 11 | stdinFileInfo, _ := os.Stdin.Stat() 12 | stdinFileMode := stdinFileInfo.Mode() 13 | 14 | log.Println("File Info Mode of os.Stdin : ", stdinFileMode.String()) 15 | 16 | // Apply the masks and determine what the file mode is. 17 | if (stdinFileMode & os.ModeCharDevice) != 0 { 18 | log.Println("os.ModeCharDevice : ", os.ModeCharDevice) 19 | log.Println("Binary AND Result : ", (stdinFileMode & os.ModeCharDevice)) 20 | 21 | fmt.Println("Input from Terminal") 22 | } else if (stdinFileMode & os.ModeNamedPipe) != 0 { 23 | log.Println("os.ModeNamedPipe : ", os.ModeNamedPipe) 24 | log.Println("Binary AND Result : ", (stdinFileMode & os.ModeNamedPipe)) 25 | 26 | fmt.Println("Input from Pipe") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /9_a_better_way_of_handling_stdin/example3/README.md: -------------------------------------------------------------------------------- 1 | Command: 2 | ``` 3 | go run main.go 4 | ``` 5 | 6 | Output: 7 | ``` 8 | Hello, mysterious person! 9 | ``` 10 | 11 | Command: 12 | ``` 13 | printf "Corey" | go run main.go 14 | ``` 15 | 16 | Output: 17 | ``` 18 | Hello, Corey! 19 | ``` -------------------------------------------------------------------------------- /9_a_better_way_of_handling_stdin/example3/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "math/rand" 7 | "os" 8 | "time" 9 | ) 10 | 11 | func main() { 12 | var name string 13 | 14 | stdinFileInfo, _ := os.Stdin.Stat() 15 | 16 | // Assign content piped to stdin if possible, assign random name if not. 17 | if (stdinFileInfo.Mode() & os.ModeNamedPipe) != 0 { 18 | 19 | // Content is being piped, assign it to name 20 | stdinContent, _ := ioutil.ReadAll(os.Stdin) 21 | 22 | name = string(stdinContent) 23 | } else { 24 | // No content was piped, choose a random salutation. 25 | defaultNames := []string{"user", "mysterious person", 26 | "misinformed user who should be piping their name through"} 27 | 28 | // Randomization stuff, ensures seed is different on every run. 29 | rand.Seed(time.Now().UnixNano()) 30 | randomIndex := rand.Intn(len(defaultNames)) 31 | 32 | name = defaultNames[randomIndex] 33 | } 34 | 35 | fmt.Printf("Hello, %s!", name) 36 | } 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # learn-go-with-me 2 | 3 | Formerly LearnGoWithMe-Code 4 | 5 | Code for posts of my blog in learning Go, [Learn Go With Me](http://www.learngowith.me). 6 | 7 | Each directory reflects a post of the same title. The latest ones are in ascending order. 8 | 9 | --- 10 | 11 | ## Posts 12 | 13 | - [Alternate ways of importing packages](./0_alternate_ways_of_importing_packages) 14 | 15 | - [Bubble Sort](./1_bubble_sort) 16 | 17 | - [Garbage Collector Change in Go 1.3](./2_garbage_collector_change_in_go13) 18 | 19 | - [Go's Pointer Type](./3_gos_pointer_type) 20 | 21 | - [Notes on Slices](./4_notes_on_slices) 22 | 23 | - [Go's Flag Package, Creating a CLI tool](./5_gos_flag_package_creating_a_cli_tool) 24 | 25 | - [A Binary Tree](./6_binary_tree) 26 | 27 | - [Go's Time Package in a few Minutes](./7_gos_time_package_in_a_few_minutes) 28 | 29 | - [Randomize the Elements of a Byte Slice in One Line](./8_randomize_the_elements_of_a_byte_slice_in_one_line) 30 | 31 | - [A Better Way of Handling Stdin](./9_a_better_way_of_handling_stdin) 32 | 33 | --- 34 | 35 | ## License 36 | 37 | This work is copyright Corey Prak and licensed under a [Creative Commons Attribution 4.0 International](http://creativecommons.org/licenses/by/4.0/) License. 38 | 39 | Share — copy and redistribute the material in any medium or format 40 | 41 | Adapt — remix, transform, and build upon the material for any purpose, even commercially. --------------------------------------------------------------------------------