├── .gitignore ├── .markdownlint.json ├── docs ├── 404.html ├── command-line.html ├── control-structures.html ├── date-time.html ├── files.html ├── for-loops.html ├── functions.html ├── guess-game.html ├── hello.html ├── index.html ├── interfaces.html ├── json.html ├── maps.html ├── memcache.html ├── mysql.html ├── numbers.html ├── objects.html ├── read-dir.html ├── regexps.html ├── rest-api.html ├── slices.html ├── sorting.html ├── strings.html ├── structs.html ├── testing.html └── web-server.html ├── pages ├── command-line.md ├── control-structures.md ├── date-time.md ├── files.md ├── for-loops.md ├── functions.md ├── guess-game.md ├── hello.md ├── index.md ├── interfaces.md ├── json.md ├── maps.md ├── memcache.md ├── mysql.md ├── numbers.md ├── objects.md ├── read-dir.md ├── regexps.md ├── rest-api.md ├── slices.md ├── sorting.md ├── strings.md ├── structs.md ├── testing.md └── web-server.md └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | docs/.htaccess 2 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": true, 3 | "MD003": { "style": "atx" }, 4 | "MD007": { "indent": 4 }, 5 | "MD013": { "line_length": 999 }, 6 | "MD025": { "front_matter_title": false }, 7 | "MD033": { "allowed_elements": [ "span", "figure", "figcaption", "video", "asciinema-player" ] }, 8 | "no-hard-tabs": false, 9 | "whitespace": false 10 | } 11 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/command-line.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/command-line/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/control-structures.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/control-structures/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/date-time.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/date-and-time/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/files.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/files/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/for-loops.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/loops/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/functions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/functions/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/guess-game.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/guess-game/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/hello.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/hello-world/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/interfaces.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/interfaces/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/json.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/json/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/maps.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/maps/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/memcache.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/memcache/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/mysql.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/mysql/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/numbers.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/numbers/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/objects.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/objects/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/read-dir.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/directories/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/regexps.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/regexp/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/rest-api.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/rest-api/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/slices.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/arrays/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/sorting.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/sorting/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/strings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/strings/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/structs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/structs/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/testing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/testing/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/web-server.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Working with Go 9 | 10 | 11 | 12 | Page moved to https://mkaz.blog/working-with-go/web-server/ 13 | 14 | 15 | -------------------------------------------------------------------------------- /pages/command-line.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Command-line 3 | layout: page 4 | order:13 5 | --- 6 | 7 | # Command-line Args 8 | 9 | ## os.Args 10 | 11 | Command-line args are stored as a slice in `os.Args`. The first argument in list is program itself. 12 | 13 | ```go 14 | num_args := len(os.Args) 15 | ``` 16 | 17 | You can check to see if any command-line arguments were passed in 18 | 19 | ```go 20 | if num_args < 2 { 21 | fmt.Println(">> No args passed in") 22 | } 23 | ``` 24 | 25 | ## Flag Library 26 | 27 | Use the [`flag`](https://golang.org/pkg/flag/) standard library to parse command-line arguments. The flag library parses parameters passed in and flags for invalid types, invalud flags, and handles most needs for creating a command-line program. 28 | 29 | ```go 30 | var s string 31 | flag.StringVar(&s, "str", "default value", "text description") 32 | ``` 33 | 34 | Usage: 35 | 36 | ```shell 37 | $ ./program -str "Hello" 38 | ``` 39 | 40 | ## Full Example 41 | 42 | Here is a full example program showing how to use command-line arguments and flags in Go 43 | 44 | ```go 45 | package main 46 | 47 | import ( 48 | "flag" 49 | "fmt" 50 | "os" 51 | ) 52 | 53 | // global vars 54 | var str string 55 | var num int 56 | var help bool 57 | 58 | func main() { 59 | 60 | // define flags 61 | flag.StringVar(&str, "str", "default value", "text description") 62 | flag.IntVar(&num, "num", 5, "text description") 63 | flag.BoolVar(&help, "help", false, "Display Help") 64 | 65 | // parse 66 | flag.Parse() 67 | 68 | // check if help was called explicitly 69 | if help { 70 | fmt.Println(">> Display help screen") 71 | os.Exit(1) 72 | } 73 | 74 | // See values assigned 75 | fmt.Println(">> String:", str) 76 | fmt.Println(">> Number:", num) 77 | 78 | // last command-line argument 79 | fmt.Println(">> Last Item:", os.Args[num_args-1]) 80 | 81 | // the os.Args will include flags for example 82 | // go run command-line-args.go --str=Foo filename 83 | // os.Args[1] = "--str=Foo" 84 | 85 | // If you have flags and want just the arguments 86 | // then after calling flag.Parse() you can call 87 | // flag.Args which store only the args 88 | args := flag.Args() 89 | if len(args) > 0 { 90 | fmt.Println(">> Flag Arg:", args[0]) 91 | } 92 | 93 | } 94 | ``` 95 | 96 | Run with different parameters 97 | 98 | ```shell 99 | $ go run command-line.go 100 | >> No args passed in 101 | >> String: default value 102 | >> Number: 5 103 | >> Last Item: command-line.go 104 | 105 | $ go run command-line.go --str=Foo --num=8 filename 106 | >> String: Foo 107 | >> Number: 8 108 | >> Last Item: filename 109 | >> Flag Arg: filename 110 | ``` 111 | -------------------------------------------------------------------------------- /pages/control-structures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Control Structures 3 | layout: page 4 | order: 5 5 | --- 6 | 7 | # Control Structures 8 | 9 | Using If, Else, Switch and Conditionals in Go. 10 | 11 | 12 | ## If, Else 13 | 14 | Go is not picky, conditionals don't require parentheses. 15 | 16 | ```go 17 | if num > 3 { 18 | fmt.Println("Many") 19 | } 20 | ``` 21 | 22 | Go is picky, `else` must be on the same line as closing `if` bracket. 23 | 24 | ```go 25 | if num == 1 { 26 | fmt.Println("One") 27 | } else if num == 2 { 28 | fmt.Println("Two") 29 | } else { 30 | fmt.Println("Many") 31 | } 32 | ``` 33 | 34 | ## Switch Statement 35 | 36 | Using switch and case conditionals in Go. Note: Go auto breaks each case, this avoids the typical issue of cascading when forgetting a break statement. 37 | 38 | ```go 39 | switch num { 40 | case 1: 41 | fmt.Println("One") 42 | case 2: 43 | fmt.Println("Two") 44 | default: 45 | fmt.Println("Many") 46 | } 47 | } 48 | ``` 49 | 50 | An alternative switch syntax allows you to check beyond equality: 51 | 52 | ```go 53 | switch { 54 | case num == 1: 55 | fmt.Println("One") 56 | case num == 2: 57 | fmt.Println("Two") 58 | case num > 2: 59 | fmt.Println("Many") 60 | default: 61 | fmt.Println("Less than 1") 62 | } 63 | } 64 | ``` 65 | -------------------------------------------------------------------------------- /pages/date-time.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Date/Time 3 | layout: page 4 | order: 14 5 | --- 6 | 7 | # Working with Date and Time 8 | 9 | The [`time`](http://golang.org/pkg/time/) standard library provides the methods needed for working with dates and time in Go. 10 | 11 | 12 | ## Now 13 | 14 | Create a date using `time.Now()`, returns a `Time` type 15 | 16 | ```go 17 | now := time.Now() 18 | ``` 19 | 20 | Create a Unix timestamp, returns a `int64` type 21 | 22 | ```go 23 | unix := time.Unix() 24 | ``` 25 | 26 | 27 | ## Format Date 28 | 29 | Go uses a format-by-example method for formating dates. This is odd and you may never get used to it, I still haven't. There is a base date `Monday, January 2nd, 2006 at 15:04:05` and all formats specified are based off examples using that date. 30 | 31 | If you want a date in `YYYY-MM-DD` format, you would use `2006-01-02` as the format string. 32 | 33 | It is debatable what is easier to remember? The sample date or the `%b %c` formats other languages use. A way to try to remember is `Month=1, Day=2, Hour=3, Minute=4, Sec=5, Year=6` 34 | 35 | ```go 36 | fmt.Println(now.Format("Mon, Jan 2, 2006 at 3:04pm")) 37 | ``` 38 | 39 | Use a method to get any part of the date, see [`Time`](http://golang.org/pkg/time/#Time) documentation for list of available time methods. 40 | 41 | ```go 42 | fmt.Println("Year: ", now.Year()) 43 | fmt.Println("Month: ", now.Month()) 44 | ``` 45 | 46 | ## Built-in Formats 47 | 48 | The time library contains a set of [built-in constants](http://golang.org/pkg/time/#pkg-constants) to assist with standard date formatting. 49 | 50 | ```go 51 | const ( 52 | ANSIC = "Mon Jan _2 15:04:05 2006" 53 | UnixDate = "Mon Jan _2 15:04:05 MST 2006" 54 | RubyDate = "Mon Jan 02 15:04:05 -0700 2006" 55 | RFC822 = "02 Jan 06 15:04 MST" 56 | RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone 57 | RFC850 = "Monday, 02-Jan-06 15:04:05 MST" 58 | RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST" 59 | RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone 60 | RFC3339 = "2006-01-02T15:04:05Z07:00" 61 | RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00" 62 | Kitchen = "3:04PM" 63 | // Handy time stamps. 64 | Stamp = "Jan _2 15:04:05" 65 | StampMilli = "Jan _2 15:04:05.000" 66 | StampMicro = "Jan _2 15:04:05.000000" 67 | StampNano = "Jan _2 15:04:05.000000000" 68 | ) 69 | ``` 70 | 71 | An example using the constant formats 72 | 73 | ```go 74 | fmt.Println(now.Format(time.RFC850)) 75 | fmt.Println(now.Format(time.RFC1123)) 76 | ``` 77 | 78 | ## Setting a Specific Date 79 | 80 | A time zone is required when specifying a date, you can build a time zone using the LoadLocation, or you could also use the `time.UTC` constant for UTC. 81 | 82 | ```go 83 | est, _ := time.LoadLocation("EST") 84 | july4 := time.Date(1776, 7, 4, 12, 15, 0, 0, est) 85 | ``` 86 | 87 | ## Parse Dates 88 | 89 | You can parse user inputted dates using known formats by specifying the format by example 90 | 91 | ```go 92 | input_format := "1/2/2006 3:04pm" 93 | user_str := "4/16/2014 11:38am" 94 | user_date, err := time.Parse(input_format, user_str) 95 | if err != nil { 96 | fmt.Println(">>> Error parsing date string") 97 | } 98 | fmt.Println("User Date: ", user_date.Format("Jan 2, 2006 @ 3:04pm")) 99 | ``` 100 | 101 | ## Date/Time Comparisons 102 | 103 | You can use `Before()`, `After()`, or `Equal()` to compare dates. 104 | 105 | ```go 106 | if july4.Before(now) { 107 | fmt.Println("July 4 is before Now ") 108 | } 109 | ``` 110 | 111 | ## Date Arithmetic 112 | 113 | The Time library also includes a [`Duration type`](https://golang.org/pkg/time/#Duration) which represents the different between two dates. The Duration type does not include days due to timezones and daylight savings. 114 | 115 | Calculate a `Duration:` 116 | 117 | ```go 118 | diff := now.Sub(july4) 119 | ``` 120 | 121 | Use a `Duration`: 122 | 123 | ```go 124 | fmt.Printf("July 4 was about %d hours ago \n", diff.Hours()) 125 | ``` 126 | 127 | You can add dates using Durations 128 | 129 | ```go 130 | twodaysDiff := time.Hour * 24 * 2 131 | twodays := now.Add(twodaysDiff) 132 | fmt.Println("Two Days: ", twodays.Format(time.ANSIC)) 133 | ``` 134 | -------------------------------------------------------------------------------- /pages/files.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Files 3 | layout: page 4 | order: 9 5 | --- 6 | 7 | # Working with Files 8 | 9 | ## Reading File 10 | 11 | You can read a complete file in using `ioutil.ReadFile`.
See [ReadFile documentation](https://golang.org/pkg/io/ioutil/#ReadFile)
The function returns two variables, the first the content of the file. The second variable is the error if one occurred. If no error, than `err` will be `nil` 12 | 13 | ```go 14 | filename := "./extras/rabbits.txt" 15 | 16 | content, err := ioutil.ReadFile(filename) 17 | if err != nil { 18 | log.Fatalln("Error reading file", filename) 19 | } 20 | ``` 21 | 22 | The content is returned as a `[]byte` and not a string. You need to cast to a string to use as such, for example to display. Use `string()` to cast a `[]byte` to `string` type. 23 | 24 | ```go 25 | fmt.Println(string(content)) 26 | ``` 27 | 28 | ## Check if File Exists 29 | 30 | One of the above errors can be if the file does not exist. You can use [`os.Stat`](https://golang.org/pkg/os/#Stat) to check explicitly if file exists without trying to open. 31 | 32 | ```go 33 | if _, err := os.Stat("junk.foo"); os.IsNotExist(err) { 34 | fmt.Println(">>>") 35 | fmt.Println("File: junk.foo does not exist") 36 | } 37 | ``` 38 | 39 | ## Read File Line-by-Line 40 | 41 | One way to process a file line by line, would be to read the entire file in, like the first example above, and then split on the line ending. 42 | 43 | ```go 44 | lines = strings.split( string(content), "\n" ) 45 | ``` 46 | 47 | The above is perfectly fine and works for most files. If you have a large file, for example one that can not be stored in memory, you can use the `bufio` package.
See [bufio package](https://golang.org/pkg/bufio) documentaiton.
48 | 49 | Here is a way to process a large file line-by-line in golang. 50 | 51 | ```go 52 | file, err := os.Open(filename) 53 | if err != nil { 54 | fmt.Println("Error opening file: ", err) 55 | } 56 | defer file.Close() // see explanation below 57 | 58 | // Use bufio scanner, the default Scan method is by line 59 | scanner := bufio.NewScanner(file) 60 | for scanner.Scan() { 61 | line := scanner.Text() 62 | fmt.Println(line) 63 | } 64 | ``` 65 | 66 | The `defer` statement defers the execution until the surrounding function (or overall program) completes. You should always use `defer` for something that needs to be closed, or cleaned up. 67 | 68 | ## Write to a new File 69 | 70 | Use [`ioutil.WriteFile`](https://golang.org/pkg/io/ioutil/#WriteFile) to write a file out. The function takes three variables, the filename, the content (as a `[]byte`) and the file system mode. 71 | 72 | ```go 73 | outfile := "output.txt" 74 | err = ioutil.WriteFile(outfile, content, 0644) 75 | if err != nil { 76 | fmt.Println("Error writing file: ", err) 77 | } else { 78 | fmt.Println(">>>") 79 | fmt.Println("Created: ", outfile) 80 | } 81 | ``` 82 | 83 | ## Append to an existing File 84 | 85 | You can write out to an existing file appending the content using the following. 86 | 87 | ```go 88 | af, err := os.OpenFile(outfile, os.O_APPEND|os.O_WRONLY, 0644) 89 | if err != nil { 90 | fmt.Println("Error appending to file:", err) 91 | } 92 | defer af.Close() 93 | if _, err = af.WriteString("Appending this text"); err != nil { 94 | fmt.Println("Error writing to file:", err) 95 | } 96 | ``` 97 | 98 | 99 | ## Using Filepath 100 | 101 | 102 | Use the `filepath` package for working with cross-platform paths properly.
See [filepath package](https://golang.org/pkg/path/filepath/) documentaiton.
For example, use `filepath.Join` for creating a path with directory. 103 | 104 | ```go 105 | package main 106 | 107 | import ( 108 | "fmt" 109 | "path/filepath" 110 | ) 111 | 112 | func main() { 113 | fmt.Println(filepath.Join("a", "b", "file.ext")) 114 | } 115 | ``` 116 | 117 | See filepath package documentation for additional function, including splitting paths, checking filename extension, base and more. 118 | -------------------------------------------------------------------------------- /pages/for-loops.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: For Loops 3 | layout: page 4 | order: 6 5 | --- 6 | 7 | # Loops 8 | 9 | Go uses `for` for all loops, there is no `while` or `do-while` loops. 10 | 11 | ## For Loop 12 | 13 | ```go 14 | 15 | alphas := []string{"abc", "def", "ghi"} 16 | 17 | // standard for loop 18 | for i := 0; i < len(alphas); i++ { 19 | fmt.Printf("%d: %s \n", i, alphas[i]) 20 | } 21 | 22 | // counting backwards 23 | for i := len(alphas)-1; i >= 0; i-- { 24 | fmt.Printf("%d: %s \n", i, alphas[i]) 25 | } 26 | ``` 27 | 28 | ## Using Range 29 | 30 | Iterating over an array is easier using `range` function. 31 | 32 | ```go 33 | for i, val := range alphas { 34 | fmt.Printf("%d: %s \n", i, val) 35 | } 36 | ``` 37 | 38 | If you did not care about the value and only wanted the index 39 | 40 | ```go 41 | for i := range alphas { 42 | fmt.Println(i) 43 | } 44 | ``` 45 | 46 | If you did not care about the index and only the value, you need to use the `_` character. 47 | 48 | ```go 49 | for _, val := range alphas { 50 | fmt.Println(val) 51 | } 52 | ``` 53 | 54 | ## Use For like While 55 | 56 | ```go 57 | x := 0 58 | for x < 10 { 59 | fmt.Println(x) 60 | x++ 61 | } 62 | ``` 63 | 64 | ## Infinite Loop 65 | 66 | ```go 67 | for { 68 | fmt.Print(".") 69 | } 70 | ``` 71 | 72 | -------------------------------------------------------------------------------- /pages/functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Functions 3 | layout: page 4 | order: 4 5 | --- 6 | 7 | # Functions 8 | 9 | Examples on how to use functions in Go. 10 | 11 | ## Basic Function 12 | 13 | An example of a basic function accepting one parameter and no return value. The parameter type must be specified in the function definition. 14 | 15 | ```go 16 | func Echo(s string) { 17 | fmt.Println(s) 18 | } 19 | ``` 20 | 21 | ## Function with Return Value 22 | 23 | Defining a function with a return value, you must specify the type for the return value. 24 | 25 | ```go 26 | func Say(s string) string { 27 | phrase := "Hello " + s 28 | return phrase 29 | } 30 | ``` 31 | 32 | ## Named Returned Value 33 | 34 | You can define a function with a named return variable. By using a named variable it initializes the variables. Also, by using a named variable you do not need to include the variable in return statement it will return the current value of the variable on return. 35 | 36 | ```go 37 | func Say(s string) (phrase string) { 38 | phrase = "Hello " + s 39 | return 40 | } 41 | ``` 42 | 43 | ## Multiple Parameters 44 | 45 | Function with multiple parameters and return values 46 | 47 | ```go 48 | func Divide(x, y float64) (float64, float64) { 49 | q := math.Trunc(x / y) 50 | r := math.Mod(x, y) 51 | return q, r 52 | } 53 | ``` 54 | 55 | Function with multiple parameters and named return values. If the types are the same you can specify the type once at the end 56 | 57 | ```go 58 | func Divide2(x, y float64) (q, r float64) { 59 | q = math.Trunc(x / y) 60 | r = math.Mod(x, y) 61 | return 62 | } 63 | ``` 64 | 65 | ## Variadic Parameters 66 | 67 | A variadic function is a function that accepts an arbitrary number of arguments. Here is an example function accepting any number of ints. A slice is created out of the parameters passed in. 68 | 69 | ```go 70 | func Sum(x ...int) int { 71 | sum := 0 72 | for _, v := range x { 73 | sum += v 74 | } 75 | return sum 76 | } 77 | ``` 78 | 79 | You can call the function with multiple parameters: 80 | 81 | ```go 82 | sum := Sum(1,3,5,7) 83 | fmt.Println(sum) 84 | ``` 85 | 86 | You can also call using the spread operator: 87 | 88 | ```go 89 | nums := []int{1, 2, 3, 4, 5 } 90 | sum := Sum(nums...) 91 | fmt.Println(sum) 92 | ``` 93 | 94 | -------------------------------------------------------------------------------- /pages/guess-game.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Guessing Game 3 | layout: page 4 | order: 18 5 | --- 6 | 7 | # Guessing Game 8 | 9 | An example of the guessing game picking a number between 1-100. 10 | 11 | 12 | ## Random umber 13 | 14 | The [`math/rand`](https://golang.org/pkg/math/rand/) standard library is used to generate the random number. 15 | 16 | Note, you must seed the generator, for random this is easiest done using `time.Now().UnixNano()`. You can also seed the generator with a known value, such as a user id to get a deterministic random number. 17 | 18 | ```go 19 | rand.Seed(time.Now().UnixNano()) 20 | fmt.Println(rand.Intn(100)) 21 | ``` 22 | 23 | ## Example Game 24 | 25 | Here is the example guessing game 26 | 27 | ```go 28 | package main 29 | 30 | import ( 31 | "fmt" 32 | "math/rand" 33 | "time" 34 | ) 35 | 36 | // automatically called on start 37 | func init() { 38 | // new random seed 39 | rand.Seed(time.Now().UnixNano()) 40 | } 41 | 42 | func main() { 43 | // variable to store guess 44 | var guess int 45 | 46 | // variable to store number of guesses 47 | var count int 48 | 49 | // pick number to guess, add 1 since Intn gives [0,99] 50 | num := rand.Intn(100) + 1 51 | 52 | fmt.Println(">> I'm thinking of a number between 1-100 << ") 53 | 54 | // guessing loop 55 | for { 56 | // prompt user for guess 57 | fmt.Print("Guess: ") 58 | _, err := fmt.Scanf("%d", &guess) 59 | if err == nil { 60 | count += 1 // increment guess counter 61 | if guess > num { 62 | fmt.Println(" >> Too high ") 63 | } else if guess < num { 64 | fmt.Println(" >> Too low ") 65 | } else { 66 | fmt.Printf("Correct! It took you %d guesses!\n", count) 67 | break 68 | } 69 | } else { // an error with input 70 | fmt.Println(">> Please input a number") 71 | } 72 | } 73 | } 74 | ``` 75 | 76 | -------------------------------------------------------------------------------- /pages/hello.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hola Mundo 3 | layout: page 4 | order: 1 5 | --- 6 | 7 | # Hola Mundo in Go 8 | 9 | Here is your first go program. 10 | 11 | ```go 12 | package main 13 | 14 | import "fmt" 15 | 16 | func main() { 17 | fmt.Println("Hola Mundo!") 18 | } 19 | ``` 20 | 21 | All programs must be part of a package, you use `main` as the package for executable programs. 22 | 23 | You must import all packages used, including the standard library packages. In this example, the standard library [`fmt`](https://golang.org/pkg/fmt/) is used for formatted I/O. 24 | 25 | The standard library is your best friend in Go, it is extensive, often you will not need any third-party dependencies and can rely on just features in the standard library. You can browse all available standard library packages at: http://golang.org/pkg/. 26 | 27 | The main package requires a `main()` function, this is called when the program is run. 28 | 29 | Go will run `init()` function before `main()`, if it exists. 30 | 31 | Here is an expanded Hello World program that uses a global variable `phrase` defined as a string. All variables have types. The go compiler will automatically detect the type if possible. 32 | 33 | ```go 34 | package main 35 | 36 | import "fmt" 37 | 38 | var phrase string 39 | 40 | func init() { 41 | phrase = "Hola Mundo!" 42 | } 43 | 44 | func main() { 45 | fmt.Println(phrase) 46 | } 47 | ``` 48 | 49 | To run the program in your terminal, save to a file `hello.go` and run using `go run`: 50 | 51 | ```shell 52 | $ go run hello.go 53 | Hola Mundo! 54 | ``` 55 | -------------------------------------------------------------------------------- /pages/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Working with Go 3 | layout: page 4 | unlisted: yes 5 | --- 6 | 7 | # Working with Go 8 | 9 | Working with Go is a set of examples in Go (golang) to get an experienced programmer familiar with Go. The Go language is often referred to as golang to help searches. 10 | 11 | Initially started as code and inline comments, but I found it more difficult to read and reference so migrated the content to this online tutorial. 12 | 13 | ## Install Go 14 | 15 | Go is distributed as a binary on the major platforms, Linux, FreeBSD, Mac OS X and Windows. It is available for both 32-bit and 64-bit architectures. See the official Getting Started with Go page for downloads and more instructions. 16 | 17 | Go is available in most Linux package environments: 18 | 19 | Ubuntu install: `apt-get install golang` 20 | 21 | Arch/Manjaro install: `pacman -S go` 22 | 23 | 24 | ## Running Go 25 | 26 | Go is a compiled language, you first need to compile program and then run the compiled binary. Go creates a single binary file that includes all necessary dependencies. This is convenient, once a binary is built you can copy and run to any similar system. 27 | 28 | Once you have Go installed, you can build a program: 29 | 30 | ```shell 31 | $ go build hello.go 32 | ``` 33 | 34 | This will create the binary `hello`, you can then run: 35 | 36 | ```shell 37 | $ ./hello 38 | >> Hola Mundo! 39 | ``` 40 | 41 | These lessons use `$` as the command prompt, and `>>` as the output from the program. 42 | 43 | Go includes a convenience function `run` that allows you to build and run in a single command. Note: this does not produce a binary. 44 | 45 | ```shell 46 | $ go run hello.go 47 | >> Hola Mundo! 48 | ``` 49 | 50 | ## Development Environment 51 | 52 | Go is purposely light-weight and simple, making it quite flexible for just about any set of developer tools. A full blown IDE, such as Eclipse, is rarely used. Most developers opt for their favorite text editor and the terminal to run. This is how I develop on Linux. 53 | 54 | 55 | 56 | My primary editor is **Vim**. I recommend using the vim-go package which includes syntax support, and some convenience functions. 57 | 58 | 59 | 60 | Go has two tools that can automatically format your source code to the Go coding standard, `gofmt` comes with the standard install and `goimports` which will format and auto adjust import statements as needed. 61 | 62 | 63 | 64 | I highly recommend `goimports` because Go will not compile if imports are missing or extra. The `goimports` command saves this hassle when adding removing things during development. 65 | 66 | Whatever editor you use, I recommend installing and configuring goimports to automatically run on save. 67 | 68 | Install goimports: 69 | 70 | ```shell 71 | $ go get golang.org/x/tools/cmd/goimports 72 | ``` 73 | 74 | For vim, you can setup to auto run `goimports` on save using vim-go: 75 | 76 | ```vim 77 | let g:go_fmt_command = "goimports" 78 | ``` 79 | 80 | ## Contribute 81 | 82 | Working with Go source files are hosted at https://github.com/mkaz/working-with-go 83 | 84 | 85 | Additions, corrections and any contributions are encouraged, please submit a pull request with your change or an issue for a bug or fix. Thanks to all the contributors! 86 | 87 | 88 | ## Resources 89 | 90 | This set of examples assumes a certain level of programming experience and is intended for someone learning the Go language and not someone new to programming altogether. 91 | 92 | If you are starting out and want to learn how to program and choose Go as your first language, check out Learn Programming in Go 93 | 94 | The official Go language site has a Tour of Go that is an interactive walk through, another good introduction to the language. 95 | -------------------------------------------------------------------------------- /pages/interfaces.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Interfaces 3 | layout: page 4 | order: 24 5 | --- 6 | 7 | # Interfaces 8 | 9 | An interface in Go is a type that defines a set of methods. Interfaces are the core of Go's type system. A type is said to satisfy an interface if it implements all the methods defined in that interface. 10 | 11 | 12 | ## Empty Interface 13 | 14 | The simplest example is the empty `interface{}`. This empty interface defines no methods thus all types implement it. This is often used to define a function that accepts any type, for example `fmt.Print` accepts any type and defined using 15 | 16 | ```go 17 | func Print(a ...interface{}) (n int, err error) { 18 | return Fprint(os.Stdout, a...) 19 | } 20 | ``` 21 | 22 | The `...` is the spread operator, it allows for any number of `interface{}` types as arguments to the function. 23 | 24 | 25 | ## Interface with Methods 26 | 27 | Here is an example interface defining a single method. This defines a `Vehicle` interface as one that has the method `Alert()` 28 | 29 | ```go 30 | type Vehicle interface { 31 | Alert() string 32 | } 33 | ``` 34 | 35 | Any type that implements the `Alert()` method is said to satisfy the `Vehicle` interface. 36 | 37 | When defining a struct you do not explicitly specify the interface it implements. Go determines automatically if a given type satisfies an interface if it defines all the methods. 38 | 39 | ```go 40 | type Car struct { } 41 | 42 | func (c Car) Alert() string { 43 | return "Honk! Honk!" 44 | } 45 | ``` 46 | 47 | Defining another type: 48 | 49 | ```go 50 | type Bicycle struct { } 51 | 52 | func (b Bicycle) Alert() string { 53 | return "Ring! Ring!" 54 | } 55 | ``` 56 | 57 | With the above definitions, you can create an array of Vehicles like so: 58 | 59 | ```go 60 | package main 61 | 62 | import "fmt" 63 | 64 | type Vehicle interface { 65 | Alert() string 66 | } 67 | 68 | type Car struct { } 69 | 70 | func (c Car) Alert() string { 71 | return "Honk! Honk!" 72 | } 73 | 74 | type Bicycle struct { } 75 | 76 | func (b Bicycle) Alert() string { 77 | return "Ring! Ring!" 78 | } 79 | 80 | func main() { 81 | c := Car{} 82 | b := Bicycle{} 83 | 84 | vehicles := []Vehicle{c, b} 85 | for _, v := range vehicles { 86 | fmt.Println(v.Alert()) 87 | } 88 | } 89 | ``` 90 | -------------------------------------------------------------------------------- /pages/json.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: JSON 3 | layout: page 4 | order: 16 5 | --- 6 | 7 | # Working with JSON 8 | 9 | Use the [`encoding/json`](http://golang.org/pkg/encoding/json/) standard library for encoding to and decoding from JSON. 10 | 11 | 12 | ## Encoding to JSON 13 | 14 | Encoding a Go struct to JSON format uses the [`json.Marshal`](https://golang.org/pkg/encoding/json/#Marshal) method, this returns a `[]byte` of the struct. 15 | 16 | ```go 17 | // Create a struct to match the format of JSON 18 | type Person struct { 19 | Name string 20 | City string 21 | } 22 | 23 | p := Person{ Name: "Marcus", City: "San Francisco" } 24 | 25 | json, err := json.Marshal(p) 26 | if err != nil { 27 | fmt.Println("JSON Encoding Error", err) 28 | } 29 | 30 | fmt.Println(string(json)) 31 | ``` 32 | 33 | ## Decode from JSON 34 | 35 | To decode a JSON string to a Go struct, use the [`json.Unmarshal`](https://golang.org/pkg/encoding/json/#Unmarshal) method. Unmarshal accepts the `[]byte` of the JSON string to decode, and a pointer to the struct that matches the data structure. 36 | 37 | ```go 38 | json_str := `{ "Name": "Marcus", "City": "San Jose"}` 39 | var p Person 40 | 41 | if err := json.Unmarshal([]byte(json_str), &p); err != nil { 42 | fmt.Println("Error parsing JSON: ", err) 43 | } 44 | 45 | // output result 46 | fmt.Printf("Name: %v, City: %v\n", person.Name, person.City) 47 | ``` 48 | 49 | ### Partial Data 50 | 51 | If a variable is already defined with values, the Unmarshaling will "fill in" the variable with the additional values from JSON. 52 | 53 | ### Read JSON from a File 54 | 55 | Since `Unmarshal` expects a `[]byte` to be read, reading from a file is straight-forward. 56 | 57 | ```go 58 | var people []Person 59 | 60 | file, err := ioutil.ReadFile("names.json") 61 | if err != nil { 62 | fmt.Println("Error reading file") 63 | } 64 | 65 | // the names.json file has an array of person objects, so read into people 66 | if err := json.Unmarshal(file, &people); err != nil { 67 | fmt.Println("Error parsing JSON", err) 68 | } 69 | 70 | // output result 71 | fmt.Println(people) 72 | ``` 73 | 74 | ## Mapping Struct and JSON Field 75 | 76 | The JSON field names may not always match the struct names. Go will automatically manage uppercase and lowercase fields, but if they are completely different you can use struct field tags to label. 77 | 78 | ```go 79 | type Person { 80 | Name string `json:"username"` 81 | City string `json:"municipality"` 82 | } 83 | ``` 84 | 85 | By defining the struct with the field tags, the Marshal and Unmarshaling will take the Go struct and write them to those JSON fields. 86 | 87 | ```go 88 | p := Person{ Name: "Marcus", City: "San Francisco" } 89 | json, _ := json.Marshal(p) 90 | fmt.Println(string(json)) 91 | 92 | >> { "username": "Marcus", "municipality": "San Francisco" } 93 | ``` 94 | 95 | ### Ignore Field 96 | 97 | You can ignore a field from being encoded or decoded to JSON, using `-` definition. 98 | 99 | ```go 100 | type Person { 101 | Name string 102 | City string 103 | Phone string `json:"-"` 104 | } 105 | ``` 106 | 107 | The `Phone` field will be omitted from JSON operations. 108 | 109 | ### Omit Empty Fields 110 | 111 | Set a field to be ignored when empty, use `omitempty` so JSON encoding will not include the field. 112 | 113 | ```go 114 | type Person { 115 | Name string 116 | City string 117 | Phone string `json:",omitempty"` 118 | } 119 | ``` 120 | 121 | -------------------------------------------------------------------------------- /pages/maps.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Maps 3 | layout: page 4 | order: 8 5 | --- 6 | 7 | # Working with Maps 8 | 9 | A map is an associative array data type. You can define a map that uses any data type for the key or value. 10 | 11 | ## Make a Map 12 | 13 | Map uses the built-in `make` function to initialize, this creates an empty map with no keys. 14 | 15 | ```go 16 | m := make(map[string]string) 17 | m["c"] = "Cyan" 18 | m["y"] = "Yellow" 19 | m["m"] = "Magenta" 20 | m["k"] = "Black" 21 | ``` 22 | 23 | You can also create the values on initialization using. 24 | 25 | ```go 26 | var m = map[string]string{ 27 | "c": "Cyan", 28 | "y": "Yellow", 29 | "m": "Magenta", 30 | "k": "Black", 31 | } 32 | ``` 33 | 34 | ## Iterate over a Map 35 | 36 | Use the same `range` function for iterating over a map, it returns the `key, value` pair. 37 | 38 | ```go 39 | for k, v := range m { 40 | fmt.Printf("Key: %s, Value: %s", k, v) 41 | } 42 | ``` 43 | 44 | ## Retrieve a Map Item 45 | 46 | Get a single map item using brackets 47 | 48 | ```go 49 | c = m["c"] 50 | ``` 51 | 52 | 53 | ## Delete a Map Item 54 | 55 | Use the `delete` built-in function, passing map and key. 56 | 57 | ```go 58 | delete(m, "c") 59 | ``` 60 | 61 | ## Test Item Exists 62 | 63 | Test if a map contains an item, by checking the second value returned when fetching an item. If the item does not exists, it will be false. 64 | 65 | If the item does not exist the value returned will be the zero value, however the item may exist as the zero value in the map, so it is best practice to check the second value returned. 66 | 67 | ```go 68 | c, ok = m["p"] 69 | ``` 70 | 71 | 72 | -------------------------------------------------------------------------------- /pages/memcache.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Memcache 3 | layout: page 4 | order: 22 5 | --- 6 | 7 | # Storing Objects in Memcache 8 | 9 | How to store objects in memcache using [bradfitz/gomemcache](https://github.com/bradfitz/gomemcache) package. Memcache stores data as `[]byte`, so you need to first encode the object prior to storing. 10 | 11 | I typically encode using JSON, often the data is already or will soon be in JSON format, plus human readable helps debugging. If space and performance is a concern, see [`encoding/gob`](https://golang.org/pkg/encoding/gob/) for another format. 12 | 13 | ```go 14 | package main 15 | 16 | import ( 17 | "encoding/json" 18 | "fmt" 19 | 20 | "github.com/bradfitz/gomemcache/memcache" 21 | ) 22 | 23 | // define Dog object type 24 | type Dog struct { 25 | Name string 26 | Color string 27 | } 28 | 29 | func main() { 30 | 31 | // connect to memcache server 32 | mc := memcache.New("127.0.0.1:11211") 33 | 34 | // try to pull from memcache 35 | fetchItem, err := mc.Get("dog") 36 | 37 | // check for cache hit 38 | if err != memcache.ErrCacheMiss { 39 | if err != nil { 40 | fmt.Println("Error fetching from memcache", err) 41 | } else { 42 | fmt.Println("Cache hit!") 43 | 44 | dog, err := DecodeData(fetchItem.Value) 45 | if err != nil { 46 | fmt.Println("Error decoding data from memcache", err) 47 | } else { 48 | fmt.Println("Dog name is: ", dog.Name) 49 | } 50 | } 51 | } 52 | 53 | // create instance of object and set properties 54 | spot := Dog{Name: "Spot", Color: "brown"} 55 | 56 | // create memcache item to store 57 | setItem := memcache.Item{ 58 | Key: "dog", 59 | Value: EncodeData(spot), 60 | Expiration: 300 61 | } 62 | 63 | err = mc.Set(&setItem) 64 | if err != nil { 65 | fmt.Println("Error setting memcache item", err) 66 | } 67 | 68 | // run twice 69 | } 70 | 71 | func DecodeData(raw []byte) (dog Dog, err error) { 72 | err = json.Unmarshal(raw, &dog) 73 | return dog, err 74 | } 75 | 76 | func EncodeData(dog Dog) []byte { 77 | enc, err := json.Marshal(dog) 78 | if err != nil { 79 | fmt.Println("Error encoding Action to JSON", err) 80 | } 81 | return enc 82 | } 83 | ``` 84 | -------------------------------------------------------------------------------- /pages/mysql.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: MySQL 3 | layout: page 4 | order: 23 5 | --- 6 | 7 | # Working with MySQL Database 8 | 9 | 10 | This is an example file for working with databases. Go provides an abstract datalayer using the [`database/sql`](https://golang.org/pkg/database/sql/) standard library. You need to load the specific driver your database first, than working with it is relatively the same. 11 | 12 | This example uses the [`go-sql-driver/mysql`](https://github.com/go-sql-driver/mysql). 13 | 14 | ## Example Tables 15 | 16 | You can create example table and data with the sql query below 17 | 18 | ```sql 19 | DROP TABLE IF EXISTS `posts`; 20 | 21 | CREATE TABLE `posts` ( 22 | `id` int(6) unsigned NOT NULL AUTO_INCREMENT, 23 | `title` varchar(30) NOT NULL, 24 | `body` text NOT NULL, 25 | PRIMARY KEY (`id`) 26 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 27 | 28 | INSERT INTO `posts` (`id`, `title`, `body`) 29 | VALUES 30 | (1,'Hello World','The content of the hello world'), 31 | (2,'Hello Second World','The content of the hello second world'); 32 | 33 | ``` 34 | 35 | ## Example Program 36 | 37 | ```go 38 | // standard main package 39 | package main 40 | 41 | // Necessary packages to work with mysql databases 42 | import ( 43 | "database/sql" 44 | "fmt" 45 | 46 | _ "github.com/go-sql-driver/mysql" 47 | ) 48 | 49 | // dbConn connects to the database 50 | func dbConn() (db *sql.DB) { 51 | 52 | dbDriver := "mysql" 53 | dbUser := "root" 54 | dbPass := "root" 55 | dbName := "godb" 56 | db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"@/"+dbName) 57 | if err != nil { 58 | panic(err.Error()) 59 | } 60 | return db 61 | } 62 | 63 | // Post is the key to connect database to the program 64 | type Post struct { 65 | Id int 66 | Title string 67 | Body string 68 | } 69 | 70 | // getAll gets all the records from database 71 | func getAll() { 72 | 73 | db := dbConn() 74 | 75 | selDB, err := db.Query("SELECT * FROM Posts ORDER BY id DESC") 76 | if err != nil { 77 | panic(err.Error()) 78 | } 79 | 80 | post := Post{} 81 | posts := []Post{} 82 | 83 | for selDB.Next() { 84 | 85 | var id int 86 | var title, body string 87 | 88 | err = selDB.Scan(&id, &title, &body) 89 | if err != nil { 90 | panic(err.Error()) 91 | } 92 | 93 | post.Id = id 94 | post.Title = title 95 | post.Body = body 96 | 97 | posts = append(posts, post) 98 | } 99 | 100 | for _, post := range posts { 101 | fmt.Println(post.Title) 102 | } 103 | 104 | defer db.Close() 105 | } 106 | 107 | // getOne gets only one record from database 108 | func getOne(postId int) { 109 | 110 | db := dbConn() 111 | 112 | selDB, err := db.Query("SELECT * FROM Posts WHERE id=?", postId) 113 | if err != nil { 114 | panic(err.Error()) 115 | } 116 | 117 | post := Post{} 118 | 119 | for selDB.Next() { 120 | 121 | var id int 122 | var title, body string 123 | 124 | err = selDB.Scan(&id, &title, &body) 125 | if err != nil { 126 | panic(err.Error()) 127 | } 128 | 129 | post.Id = id 130 | post.Title = title 131 | post.Body = body 132 | 133 | } 134 | 135 | fmt.Println("Post Title : " + post.Title) 136 | fmt.Println("Post Body : " + post.Body) 137 | 138 | defer db.Close() 139 | } 140 | 141 | // add helps you to add new record to database 142 | func add() { 143 | 144 | db := dbConn() 145 | 146 | title := "Hello Second World" 147 | body := "The content of the hello second world" 148 | insertQuery, err := db.Prepare("INSERT INTO Posts(title, body) VALUES(?,?)") 149 | if err != nil { 150 | panic(err.Error()) 151 | } 152 | 153 | insertQuery.Exec(title, body) 154 | 155 | fmt.Println("ADDED: Title: " + title + " | Body: " + body) 156 | 157 | defer db.Close() 158 | 159 | } 160 | 161 | // update helps you to update an existing record in the database 162 | func update(postId int) { 163 | 164 | db := dbConn() 165 | 166 | title := "Hello 1 World" 167 | body := "The content of the hello 1 world" 168 | updateQuery, err := db.Prepare("UPDATE Posts SET title=?, body=? WHERE id=?") 169 | if err != nil { 170 | panic(err.Error()) 171 | } 172 | 173 | updateQuery.Exec(title, body, postId) 174 | 175 | fmt.Println("UPDATED: Title: " + title + " | Body: " + body) 176 | 177 | defer db.Close() 178 | 179 | } 180 | 181 | // delete helps you to delete an existing record in the database 182 | func delete(postId int) { 183 | 184 | db := dbConn() 185 | 186 | deleteQuery, err := db.Prepare("DELETE FROM Posts WHERE id=?") 187 | if err != nil { 188 | panic(err.Error()) 189 | } 190 | 191 | deleteQuery.Exec(postId) 192 | 193 | fmt.Println("DELETED") 194 | 195 | defer db.Close() 196 | 197 | } 198 | 199 | func main() { 200 | 201 | //add() 202 | //update(1) 203 | //delete(1) 204 | //getOne(1) 205 | getAll() 206 | 207 | } 208 | ``` 209 | 210 | -------------------------------------------------------------------------------- /pages/numbers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Numbers 3 | layout: page 4 | order: 2 5 | --- 6 | 7 | # Working with Numbers 8 | 9 | Go is a typed language, that means each variable is given a single specific number type. The common number types in golang are int, float, int64, float64. You need to be aware that each are differnet and function definitions and usage define the precise type expected. 10 | 11 | ## Convert String to Integer 12 | 13 | The most common conversion is a `string` to an `int`, for this you use the `strconv` package.
See [strconv package](https://golang.org/pkg/strconv) documentation.
The strconv package contains various functions for converting strings to default types. 14 | 15 | Here is how to convert a string to an integer in golang: 16 | 17 | ```go 18 | str := 42 19 | ans, err := strconv.Atoi(str) 20 | if err != nil { 21 | fmt.Println("Error convert string to integer", err) 22 | } 23 | ``` 24 | 25 | ## Convert Integer to a String 26 | 27 | Converting an integer to a string is a bit easier because there is no chance of an error. So it is just the single function `strconv.Itoa()` 28 | 29 | ```go 30 | str := strconv.Itoa(42) 31 | ``` 32 | 33 | ## Convert Integer to a Float 34 | 35 | The `math` package has numerous helpful functions.
See [math package](https://golang.org/pkg/math/) documentation
However, almost of the function require using a float64, so conversions are needed. 36 | 37 | If you are specifying a number, you can force a float type by using a decimal. 38 | ```go 39 | i := 42 // int type 40 | y := 42.0 // float type 41 | ``` 42 | 43 | If an integer a variable, you can cast it to a float using 44 | ```go 45 | i := 42 46 | x := float64(i) 47 | ``` 48 | 49 | ## Convert a String to a Float 50 | 51 | To convert a string to a float, use the `strconv.ParseFloat` function, the second argument is the bitSize, 64 is probably the most common to convert to a float64 type. 52 | 53 | ```go 54 | pi := "3.14159" 55 | x, err := strconv.ParseFloat(pi, 64) 56 | if err != nil { 57 | fmt.Println("Error convert string to float", err) 58 | } 59 | ``` 60 | 61 | Note: You can print the type of a variable using `%T` in `fmt.Printf()` 62 | 63 | Example printing the type of a variable in golang: 64 | ```go 65 | fmt.Printf("Variable x has type %T and value %v", x, x ) 66 | ``` 67 | -------------------------------------------------------------------------------- /pages/objects.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Objects 3 | layout: page 4 | order: 11 5 | --- 6 | 7 | # Object Oriented Programming 8 | 9 | Go does not have objects and classes, so is not a true object oriented programming. However, you can add methods to types. This gives you most of the same ability without the added complexity of full OOP. 10 | 11 | A method is a function with a _receiver_ defined first. Using the `Dog` type from the [structs example](/structs.html). 12 | 13 | ```go 14 | package main 15 | 16 | import "fmt" 17 | 18 | type Dog struct { 19 | Name string 20 | Color string 21 | } 22 | 23 | func (d Dog) Call() { 24 | fmt.Printf("Here comes a %s dog, %s.\n", d.Color, d.Name) 25 | } 26 | 27 | func main() { 28 | 29 | // create instance of dog 30 | Spot := Dog{Name: "Spot", Color: "brown"} 31 | 32 | // call object method 33 | Spot.Call() 34 | } 35 | ``` 36 | 37 | 38 | ## Limitations 39 | 40 | You can define methods on custom types, but are limited to types that are defined in the same package as the method. So you cannot define a method on built-in types, you would first need to extend. 41 | 42 | ```go 43 | package main 44 | 45 | import "fmt" 46 | 47 | type MyInt int 48 | 49 | func (i MyInt) Double() MyInt { 50 | return i * 2 51 | } 52 | 53 | func main() { 54 | x := MyInt(3) 55 | fmt.Println(x.Double()) 56 | } 57 | ``` 58 | 59 | -------------------------------------------------------------------------------- /pages/read-dir.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Directories 3 | layout: page 4 | order: 10 5 | --- 6 | 7 | # Directories 8 | 9 | ## Read Directory Recursively 10 | 11 | Use the [`filepath.Walk`](https://golang.org/pkg/path/filepath/#Walk) function to recursively walk down a directory. 12 | 13 | The `Walk` function accepts a path, and [`WalkFunc`](https://golang.org/pkg/path/filepath/#WalkFunc) as its parameters. 14 | 15 | The `WalkFunc` signature is `func(path string, info os.FileInfo, err error) error`, below is an example using an anonymous function with that signature. 16 | 17 | In the `WalkFunc` if you want to skip an entire directory, return `filepath.SkipDir` which is a special error variable defined in the library. 18 | 19 | ```go 20 | package main 21 | 22 | import ( 23 | "fmt" 24 | "os" 25 | "path/filepath" 26 | ) 27 | 28 | func main() { 29 | path := "./dir" 30 | 31 | filepath.Walk(path, func(fn string, fi os.FileInfo, err error) error { 32 | if err != nil { 33 | fmt.Println("Walker Error: ", err) 34 | return err 35 | } 36 | 37 | if fi.IsDir() { 38 | fmt.Println("Directory: ", fn) 39 | if fi.Name() == "skipme" { 40 | return filepath.SkipDir 41 | } 42 | } else { 43 | fmt.Println("File: ", fn) 44 | } 45 | return nil 46 | }) 47 | } 48 | ``` 49 | 50 | ## Create Directory if not exists 51 | 52 | Check if directory exists, create directory if it does not. 53 | 54 | ```go 55 | pathdir := filepath.Join(path, dir) 56 | if _, err := os.Stat(pathdir); os.IsNotExist(err) { 57 | mdErr := os.Mkdir(dirpath, 0755) 58 | if mdErr != nil { 59 | fmt.Println("Error making directory", mdErr) 60 | } 61 | } 62 | ``` 63 | 64 | ## Get User Home Directory 65 | 66 | A platform independent way to get the user's home directory. 67 | 68 | ```go 69 | import "os/user" 70 | 71 | usr, err := user.Current() 72 | fmt.Println("User Home Directory:", usr.HomeDir) 73 | ``` 74 | 75 | -------------------------------------------------------------------------------- /pages/regexps.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Regexp 3 | layout: page 4 | order: 21 5 | --- 6 | 7 | # Regular Expressions 8 | 9 | Use the [`regexp`](http://golang.org/pkg/regexp/) standard library to work with regular expressions. 10 | 11 | 12 | ## Basic Regexp 13 | 14 | Create regular expression pattern to match 1 or more numbers 15 | 16 | ```go 17 | pattern := "[0-9]+" 18 | 19 | re, err := regexp.Compile(pattern) 20 | if err != nil { 21 | fmt.Println("Error compiling regex", err) 22 | } 23 | ``` 24 | 25 | ### Test if Pattern Matches 26 | 27 | Use `MatchString` to test if pattern matches 28 | 29 | ```go 30 | str := "The 12 monkeys ate 48 bananas" 31 | if re.MatchString(str) { 32 | fmt.Println("Yes, matched a number") 33 | } else { 34 | fmt.Println("No, no match") 35 | } 36 | ``` 37 | 38 | ### Return Match 39 | 40 | Use `FindString` to return match 41 | 42 | ```go 43 | result := re.FindString(str) 44 | fmt.Println("Number matched:", result) 45 | ``` 46 | 47 | ### Return Multiple Matches 48 | 49 | Use `FindAllString` to return multiple matches, specify `-1` to return all. 50 | 51 | ```go 52 | results := re.FindAllString(str, 2) 53 | for i, v := range results { 54 | fmt.Printf("Match %d: %s\n", i, v) 55 | } 56 | ``` 57 | 58 | ### Replace Match 59 | 60 | Use `ReplaceAllString` to replace matches 61 | 62 | ```go 63 | results := re.ReplaceAllString(str, "xx") 64 | fmt.Println("Result:", results) 65 | ``` 66 | 67 | ## Case Insensitive 68 | 69 | The format for Go regular expression flags is different than typical. In Golang, the flag precedes the pattern, the syntax is, let's just say, not great. Here is an example using the case insensitive flag `i` 70 | 71 | ```go 72 | ptn := `(?i)^t.` 73 | str := "To be or not to be" 74 | 75 | re, err := regexp.Compile(ptn) 76 | if err != nil { 77 | fmt.Println("Error compiling regex", err) 78 | } 79 | 80 | // match string 81 | result := re.FindString(str) 82 | fmt.Println(result) 83 | ``` 84 | 85 | ## Submatches 86 | 87 | Submatches are what Go calls the matches that are grabbed by `(.*)` inside of a regular expression. 88 | 89 | ```go 90 | str1 := "Hello @world@ Match" 91 | sub_re, _ := regexp.Compile("@(.*)@") 92 | 93 | m := sub_re.FindStringSubmatch(str1) 94 | // FindStringSubmatch returns [@world@ world] 95 | // so to just get the submatch you would use 96 | if len(m) > 1 { 97 | fmt.Println(m[1]) // submatch 98 | } 99 | ``` 100 | 101 | ### Escaping Special Characters 102 | 103 | If you wanted to match brackets or other special characters and try to just escape them like so `\[(.*)\]` you will get an error for unknown escape sequence `[` 104 | 105 | You need to double up the slashes or a nicer solution is to use string literals and wrap in ticks instead of quotes 106 | 107 | ```go 108 | str2 := "A [word] here and [there]" 109 | esc_pattern := `\[(.*?)\]` 110 | esc_re, _ := regexp.Compile(esc_pattern) 111 | 112 | // this will only find the first 113 | fmt.Println(esc_re.FindStringSubmatch(str2)) 114 | 115 | // use FindAll with second parameter for # of matches -1 = all 116 | fmt.Println(esc_re.FindAllStringSubmatch(str2, -1)) 117 | ``` 118 | 119 | -------------------------------------------------------------------------------- /pages/rest-api.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: REST API 3 | layout: page 4 | order: 20 5 | --- 6 | 7 | # REST API 8 | 9 | Use the [`net/http`](https://golang.org/pkg/net/http/) standard library to create external http calls. You can combine this with the [parsing of JSON](json.html) to work with external APIs. 10 | 11 | The following example pulls in data from the Reddit API to get latest posts from golang sub. The key to understanding JSON decoding is understanding the data structure you receive the data. Once data structs are mapped, it becomes relatively straight forward 12 | 13 | ```go 14 | package main 15 | 16 | import ( 17 | "encoding/json" 18 | "io/ioutil" 19 | "log" 20 | "net/http" 21 | ) 22 | 23 | // create data structures to hold JSON data 24 | // this needs to match the fields in the JSON feed 25 | // see sample data fetch at bottom of this file 26 | 27 | // create an individual entry data structure 28 | // this does not need to hold every field, just the ones we want 29 | type Entry struct { 30 | Title string 31 | Author string 32 | URL string 33 | Permalink string 34 | } 35 | 36 | // the feed is the full JSON data structure 37 | // this sets up the array of Entry types (defined above) 38 | type Feed struct { 39 | Data struct { 40 | Children []struct { 41 | Data Entry 42 | } 43 | } 44 | } 45 | 46 | func main() { 47 | // url of REST endpoint we are grabbing data from 48 | url := "https://www.reddit.com/r/golang/new.json" 49 | 50 | // fetch url 51 | resp, err := http.Get(url) 52 | if err != nil { 53 | log.Fatalln("Error fetching:", err) 54 | } 55 | // defer response close 56 | defer resp.Body.Close() 57 | 58 | // confirm we received an OK status 59 | if resp.StatusCode != http.StatusOK { 60 | log.Fatalln("Error Status not OK:", resp.StatusCode) 61 | } 62 | 63 | // read the entire body of the response 64 | body, err := ioutil.ReadAll(resp.Body) 65 | if err != nil { 66 | log.Fatalln("Error reading body:", err) 67 | } 68 | 69 | // create an empty instance of Feed struct 70 | // this is what gets filled in when unmarshaling JSON 71 | var entries Feed 72 | if err := json.Unmarshal(body, &entries); err != nil { 73 | log.Fatalln("Error decoing JSON", err) 74 | } 75 | 76 | // loop through the children and create entry objects 77 | for _, ed := range entries.Data.Children { 78 | entry := ed.Data 79 | log.Println(">>>") 80 | log.Println("Title :", entry.Title) 81 | log.Println("Author :", entry.Author) 82 | log.Println("URL :", entry.URL) 83 | log.Printf("Comments: http://reddit.com%s \n", entry.Permalink) 84 | } 85 | } 86 | ``` 87 | 88 | -------------------------------------------------------------------------------- /pages/slices.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Slices 3 | layout: page 4 | order: 3 5 | --- 6 | 7 | # Working with Slices 8 | 9 | Go has an array type, but it has a fixed size. Slices in Go are dynamically-sized and more flexible. Slices are the common data type you will work with. 10 | 11 | The specification for slices are `[]T` where T is the type, for example `[]string` is a set of strings, or `[]int` is a set of integers. 12 | 13 | ## Initialize 14 | 15 | Initialize an empty slice. 16 | 17 | ```go 18 | var empty []int 19 | ``` 20 | 21 | Initialize a slice with values. 22 | 23 | ```go 24 | alphas := []string{"abc", "def", "ghi", "jkl"} 25 | ``` 26 | 27 | ## Append 28 | 29 | Slices can not be modified, a new copy needs to be made, it is common to copy to the same variable. 30 | 31 | ```go 32 | var nums []int 33 | nums = append(nums, 203) 34 | nums = append(nums, 302) 35 | fmt.Println(nums) 36 | // [203 302] 37 | ``` 38 | 39 | Append multiple values at once. 40 | 41 | ```go 42 | alphas := []string{"abc", "def", "ghi", "jkl"} 43 | alphas = append(alphas, "mno", "pqr", "stu") 44 | ``` 45 | 46 | ## Common Array Operations 47 | 48 | Get length of a slice. 49 | 50 | ```go 51 | fmt.Println("Length: ", len(alphas)) 52 | ``` 53 | 54 | Retrieve a single element from slice 55 | 56 | ```go 57 | fmt.Println(alphas[1]) 58 | ``` 59 | 60 | Retrieve a slice of a slice 61 | 62 | ```go 63 | alpha2 := alphas[1:3] 64 | fmt.Println(alpha2) 65 | ``` 66 | 67 | 68 | ## Element Exists in a Slice 69 | 70 | There is no built-in function to determine if an element exists in a slice. Here is an example function to check if a string exists in an array of strings. 71 | 72 | ```go 73 | package main 74 | 75 | import "fmt" 76 | 77 | func main() { 78 | 79 | alphas := []string{"abc", "def", "ghi", "jkl"} 80 | 81 | if elemExists("def", alphas) { 82 | fmt.Println("Exists!") 83 | } 84 | } 85 | 86 | func elemExists(s string, a []string) bool { 87 | for _, v := range a { 88 | if v == s { 89 | return true 90 | } 91 | } 92 | return false 93 | } 94 | ``` 95 | 96 | -------------------------------------------------------------------------------- /pages/sorting.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Sorting 3 | layout: page 4 | order: 15 5 | --- 6 | 7 | # Sorting Arrays and Maps 8 | 9 | The [`sort`](https://golang.org/pkg/sort/) standard library is used for sorting slices, maps, and user define collections. 10 | 11 | ## Sort Alphabetical 12 | 13 | Use `sort.Strings()` to sort alphabetically 14 | 15 | ```go 16 | abc := []string{"jkl", "ghi", "abc", "def"} 17 | sort.Strings(abc) 18 | fmt.Println("Sorted ABC:", abc) 19 | ``` 20 | 21 | ## Sort Numeric 22 | 23 | Use `sort.Ints()` to sort numerically 24 | 25 | ```go 26 | nums := []int{4, 2, 12, 5, 1, 3} 27 | sort.Ints(nums) 28 | fmt.Println("Sorted Nums:", nums) 29 | ``` 30 | 31 | ## Reverse Sort 32 | 33 | Reverse sort, need to cast `abc` as a StringSlice to reverse and sort 34 | 35 | ```go 36 | sort.Sort(sort.Reverse(sort.StringSlice(abc))) 37 | fmt.Println("Reverse ABC:", abc) 38 | ``` 39 | 40 | ## Sort Maps 41 | 42 | To sort a map by keys, pull an array of keys out of the map, sort the keys and then iterate over the sorted keys. A map by itself is not sortable. 43 | 44 | ```go 45 | hash := map[string]int{ 46 | "c": 3, 47 | "a": 1, 48 | "b": 2, 49 | "e": 5, 50 | "d": 4, 51 | } 52 | 53 | // Create array of kys 54 | var keys []string 55 | for k := range hash { 56 | keys = append(keys, k) 57 | } 58 | 59 | // Sort keys 60 | sort.Strings(keys) 61 | 62 | // Use ordered keys to loop through hash 63 | for i := range keys { 64 | fmt.Printf("%s => %v\n", keys[i], hash[keys[i]]) 65 | } 66 | ``` 67 | -------------------------------------------------------------------------------- /pages/strings.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Strings 3 | layout: page 4 | order: 2 5 | --- 6 | 7 | # Working with Strings 8 | 9 | A set of examples working with strings in Golang. The `strings` standard library contains most of the functions you'll use to work with string.
See [strings package](http://golang.org/pkg/strings/) documentation
10 | 11 | Create and set a variable in one line using `:=` operator. Go will automatically determine the type by the assignment. 12 | 13 | ```go 14 | str := "This is an example string" 15 | ``` 16 | 17 | In general, Go does not use a standard object oriented notation to operate on values. This differs from languages like JavaScript and Python. Instead in Go, you typically pass in the variable you are working on to the function. Here is an example using the `Contains` function from the `strings` package: 18 | 19 | ```go 20 | exists := strings.Contains(str, "example") 21 | ``` 22 | Here is a full example program, that uses the `ToLower` function to convert a string to lowercase, and `Contains` to check if a string contains another. 23 | 24 | ```go 25 | package main 26 | 27 | import ( 28 | "fmt" // for standard output 29 | "strings" // for manipulating strings 30 | ) 31 | 32 | func main() { 33 | 34 | // create a string variable 35 | str := "HI, I'M UPPER CASE" 36 | 37 | // convert to lower case 38 | lower := strings.ToLower(str) 39 | 40 | // output to show its really lower case 41 | fmt.Println(lower) 42 | 43 | // check if string contains another string 44 | if strings.Contains(lower, "case") { 45 | fmt.Println("Yes, exists!") 46 | } 47 | } 48 | ``` 49 | 50 | ## Strings as Array of Characters 51 | 52 | Strings in Go are an array of characters and can be referenced as such. 53 | 54 | ```go 55 | str := "abcdefghijklmnopqrstuvwxyz" 56 | fmt.Println("Chars 3-10: " + str[3:10]) 57 | 58 | // printing out first 5 characters 59 | fmt.Println("First Five: " + str[:5]) 60 | 61 | // printing out from 13 to end 62 | fmt.Println("From 13 on: " + str[13:]) 63 | ``` 64 | 65 | 💡 The Go Playground is a useful online environment that runs Go code in your browser. See the above example in the Go Playground here: [https://play.golang.org/p/DC7R7XKzZ5G](https://play.golang.org/p/DC7R7XKzZ5G). I often use the playground to test out a bit of logic I'm working on. 66 | 67 | ## Split Strings 68 | 69 | Split a string on a specific character or word 70 | 71 | ```go 72 | sentence := "I'm a sentence made up of words" 73 | words := strings.Split(sentence, " ") 74 | fmt.Printf("%v \n", words) 75 | ``` 76 | 77 | If you were splitting on whitespace, using Fields is better because it will split on all whitespace characters, not just a space. 78 | 79 | ```go 80 | sentence := "I'm a sentence made up of words" 81 | fields := strings.Fields(sentence) 82 | fmt.Printf("%v \n", fields) 83 | ``` 84 | 85 | ## Join an Array of Strings 86 | 87 | In an OOP world, the `Join` function would be defined in an array package. In Go, however, it is part of the strings package, you pass in an array of strings and the separator you want to join them. 88 | 89 | ```go 90 | lines := []string{ "one", "two", "three" } 91 | str := string.Join(lines, ",") 92 | fmt.Println(str) 93 | >> one, two, three 94 | ``` 95 | 96 | ## String Replace 97 | 98 | To replace a string with another use `strings.Replace` 99 | 100 | ```go 101 | str := "The blue whale loves blue fish." 102 | newstr := strings.Replace(str, "blue", "red", 1) 103 | >> "The red whale loves blue fish." 104 | ``` 105 | 106 | The `strings.Replace` function requires passing in how many replacements it should do. Pass in `-1` to replace all occurrences. 107 | 108 | ```go 109 | str := "The blue whale loves blue fish." 110 | newstr := strings.Replace(str, "blue", "red", -1) 111 | >> "The red whale loves red fish." 112 | ``` 113 | 114 | Go version 1.12 introduced the `strings.ReplaceAll` function that does not have the fourth argument -- it, as it says, replaces all occurrences. 115 | 116 | 117 | ## Strings HasPrefix and HasSuffix 118 | 119 | The Go functions for checking if a strings starts with, or ends with, another string are `strings.HasPrefix()` and `strings.HasSuffix()`. 120 | 121 | ```go 122 | path := "/home/mkaz" 123 | isAbsolute := strings.HasPrefix(path, "/") 124 | 125 | dir := "/home/mkaz/" 126 | hasTrailingSlash := strings.HasSuffix(path, "/") 127 | ``` 128 | 129 | -------------------------------------------------------------------------------- /pages/structs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Structs 3 | layout: page 4 | order: 7 5 | --- 6 | 7 | # Working with Structs 8 | 9 | A struct is a data type in Go that is a collection of fields. A struct is the closest Go gets to objects. 10 | 11 | ## Define Struct 12 | 13 | ```go 14 | // define Dog struct 15 | type Dog struct { 16 | Name string 17 | Color string 18 | } 19 | ``` 20 | 21 | ## Create Instance 22 | 23 | Create an instance of a struct type 24 | 25 | ```go 26 | Spot := Dog{Name: "Spot", Color: "brown"} 27 | ``` 28 | 29 | An alternative way, create a blank instance, each field is set to its zero value. Access struct fields using dot notation for getting or setting. 30 | 31 | ```go 32 | var Rover Dog 33 | Rover.Name = "Rover" 34 | Rover.Color = "light tan with dark patches" 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /pages/testing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Testing 3 | layout: page 4 | order: 24 5 | --- 6 | 7 | # Testing 8 | 9 | The [Go testing package](https://golang.org/pkg/testing/) supports creating unit test in go. Your test code is written in plain go, there is not a new assert language or syntax to learn. Write go code and use `t.Fail` or `t.Error` to signal the test did not pass. 10 | 11 | To write a new test create a test file, ending in `_test.go` that includes functions with the following signature: `func TestXxx(*testing.T)` 12 | 13 | Note: The function name must start with `Test` and include a capitalized second part to identify the test routing. 14 | 15 | For example, if you want to test an `Add` function in your project: 16 | 17 | Create `add_test.go`: 18 | 19 | ```go 20 | package main 21 | 22 | import "testing" 23 | 24 | func TestAdd(t *testing.T) { 25 | sum := Add(1, 1) 26 | if sum != 2 { 27 | t.Errorf("Expected %d => Received %d", 2, sum) 28 | } 29 | } 30 | ``` 31 | 32 | Run test using: `go test` 33 | 34 | ## Test Table 35 | 36 | Use a table structure to setup and test multiple inputs and expected values. 37 | 38 | ```go 39 | func TestAdd(t *testing.T) { 40 | var testData = []struct { 41 | param1 int 42 | param2 int 43 | expect int 44 | }{ 45 | { 1, 2, 3 }, 46 | { 0, 1, 1 }, 47 | { 1, 0, 1 }, 48 | { -1, 1, 0 }, 49 | { -1, -1, -2 }, 50 | } 51 | 52 | for _, td := range testData { 53 | result := Add(td.param1, td.param2) 54 | if td.expect != result { 55 | t.Errorf("Expected %s but received %s", td.expect, result) 56 | } 57 | } 58 | } 59 | ``` 60 | 61 | 62 | -------------------------------------------------------------------------------- /pages/web-server.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Web Server 3 | layout: page 4 | order: 17 5 | --- 6 | 7 | # Web Server 8 | 9 | The standard library [`net/http `](https://golang.org/pkg/net/http/) provides a powerful set of tools you can use to make your own web server. 10 | 11 | See my Lanyon project: [https://github.com/mkaz/lanyon](https://github.com/mkaz/lanyon) for a more complete server created in Go which converts markdown to html. 12 | 13 | ```go 14 | package main 15 | 16 | import ( 17 | "fmt" 18 | "log" 19 | "net/http" 20 | ) 21 | 22 | func main() { 23 | // associate URLs requested to functions that handle requests 24 | http.HandleFunc("/hello", helloRequest) 25 | http.HandleFunc("/", getRequest) 26 | 27 | // start web server 28 | log.Println("Listening on http://localhost:9999/") 29 | log.Fatal(http.ListenAndServe(":9999", nil)) 30 | } 31 | 32 | // basic handler for /hello request 33 | func helloRequest(w http.ResponseWriter, r *http.Request) { 34 | 35 | // Fprint writes to a writer, in this case the http response 36 | fmt.Fprint(w, "Hallo Welt") 37 | return 38 | } 39 | 40 | // this function simply serves up the file requested, or 41 | // an index list if a directory is requested 42 | func getRequest(w http.ResponseWriter, r *http.Request) { 43 | file_requested := "./" + r.URL.Path 44 | http.ServeFile(w, r, file_requested) 45 | return 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | 2 | # Working with Go 3 | 4 | ## View online at: https://mkaz.blog/working-with-go/ 5 | 6 | Working with Go is a set of examples for Go (golang) to help an experienced programmer become familiar with the Go language. Go is often referred to as golang to help searches. 7 | 8 | 9 | ## Resources 10 | 11 | This set of examples assumes a base level of programming experience and is intended for someone learning the Go language from another language; not necessarily someone new to programming altogether. 12 | 13 | If you are starting out and want to learn how to program and choose Go as your first language, check out [Learn Programming in Go](http://www.golang-book.com/) 14 | 15 | The official site has a [Tour of Go](http://tour.golang.org/) which is an interactive walk through, another good introduction to the language. 16 | 17 | I'm also a big fan of [Go by Example](https://gobyexample.com/) which is quite similar. 18 | 19 | 20 | ## Contribute 21 | 22 | The site is sourced from markdown files in the `pages` directory. Any additions, corrections, suggestions or any contributions are appreciated. 23 | 24 | To submit a pull request, make your edit to the file in `pages` directory. 25 | 26 | Working with Go was started by Marcus Kazmierczak. Thanks to all the contributors who have helped make it even better. 27 | 28 | 29 | ## License 30 | 31 | Working with Go is licensed under a Creative Commons Attribution 4.0 International License. 32 | --------------------------------------------------------------------------------