```
45 |
46 | ## References
47 |
48 | * [Golang Code Examples web site] (http://l3x.github.io/golang-code-examples/)
49 | * [A Tour of Go] (http://tour.golang.org/)
50 | * [An Introduction to Programming in Go] (http://www.golang-book.com/)
51 | * [How to Write Go Code] (http://golang.org/doc/code.html)
52 | * [Application Development with Lex Sheehan] (http://lexsheehan.blogspot.com/)
53 |
54 | ### License
55 | This project is licensed under a Simplified BSD license. Please read the [LICENSE file](LICENSE).
--------------------------------------------------------------------------------
/custom-error-handling.go:
--------------------------------------------------------------------------------
1 | /*
2 | filename: custom-error-handling.go
3 | author: Lex Sheehan
4 | copyright: Lex Sheehan LLC
5 | license: GPL
6 | status: published
7 | comments: http://l3x.github.io/golang-code-examples/2014/07/14/custom-error-handling.html
8 | */
9 | package main
10 |
11 | import (
12 | "fmt"
13 | "time"
14 | )
15 |
16 | type Err struct {
17 | errNo int
18 | when time.Time
19 | msg string
20 | }
21 |
22 | func (e *Err) Error() string {
23 | return fmt.Sprintf("%v [%d] %s", e.when, e.errNo, e.msg)
24 | }
25 | func (err Err) errorNumber() int {
26 | return err.errNo
27 | }
28 |
29 | type ErrWidget_A struct {
30 | Err // Err is an embedded struct - ErrWidget_A inherits it's data and behavior
31 | }
32 | // a behavior only available for the ErrWidget_A
33 | func (e ErrWidget_A) Error() string {
34 | fmt.Println("do special ErrWidget_A thing...")
35 | return fmt.Sprintf("%s [%d] %s", e.when, e.errNo, e.msg)
36 | }
37 | // a behavior only available for the ErrWidget_A
38 | func (e ErrWidget_A) optionalErrHandlingOperation() {
39 | fmt.Println("Email the admins...\n")
40 | }
41 |
42 | type ErrWidget_B struct {
43 | Err // Err is an embedded struct - ErrWidget_B inherits it's data and behavior
44 | }
45 | // a behavior only available for the Widget_B
46 | func (e ErrWidget_B) Error() string {
47 | fmt.Println("do special Widget_B thing...")
48 | return fmt.Sprintf("%s [%d] %s", e.when, e.errNo, e.msg)
49 | }
50 | // a behavior only available for the Widget_B
51 | func (e ErrWidget_B) optionalErrHandlingOperation() {
52 | fmt.Println("SMS operations manager...\n")
53 | }
54 |
55 | func run() error {
56 | return &Err{
57 | 8001,
58 | time.Now(),
59 | "generic error occurred\n",
60 | }
61 | }
62 |
63 | func run2() *ErrWidget_B {
64 | errB := new(ErrWidget_B)
65 | errB.errNo = 6001
66 | errB.when = time.Now()
67 | errB.msg = "Widget_B error occurred"
68 | return errB
69 | }
70 |
71 | func RunWidget(modelNo int) (string, error) {
72 | // Run valid widgets
73 | switch modelNo {
74 | case 1:
75 | return fmt.Sprintf("run widget model %d", modelNo), nil
76 | case 2:
77 | return fmt.Sprintf("run widget model %d", modelNo), nil
78 | default:
79 | // Error condition - unknown widget model number
80 | errA := new(ErrWidget_A)
81 | errA.errNo = 5002
82 | errA.when = time.Now()
83 | errA.msg = "Widget_A error occurred"
84 | return fmt.Sprintf("unable to run unknown model %d", modelNo), errA
85 | }
86 | }
87 |
88 | // Split multiple (variadic) return values into a slice of values
89 | // in this case, where [0] = value and [1] = the error message
90 | func split(args ...interface{}) []interface{} {
91 | return args
92 | }
93 |
94 | func main() {
95 |
96 | // Execute RunWidget function and handle error if necessary
97 | msg := ""
98 | // RunWidget(1) succeeds
99 | x := split(RunWidget(1))
100 | msg = "\n\n"; if x[1] != nil {msg = fmt.Sprintf(", err(%v)\n\n", x[1])}
101 | fmt.Printf("RunWidget(1) => result(%s)" + msg, x[0])
102 |
103 | // RunWidget(2) succeeds
104 | x = split(RunWidget(2))
105 | msg = "\n\n"; if x[1] != nil {msg = fmt.Sprintf(", err(%v)\n\n", x[1])}
106 | fmt.Printf("RunWidget(2) => result(%s)" + msg, x[0])
107 |
108 | // RunWidget(666) fails -
109 | x = split(RunWidget(666))
110 | msg = "\n\n"; if x[1] != nil {msg = fmt.Sprintf(", err(%v)\n\n", x[1])}
111 | fmt.Printf("RunWidget(666) => result(%s)" + msg, x[0])
112 |
113 |
114 | // Throw generic custom error type and handle it
115 | if err := run(); err != nil { fmt.Println(err) }
116 |
117 | // Throw ErrWidget_B error and handle it by printing and running optional custom behavior
118 | widget_B_error := run2(); if widget_B_error.errNo != 0 {
119 | fmt.Println(widget_B_error)
120 | }
121 | fmt.Println("")
122 |
123 |
124 | timeNow := time.Now()
125 | // Create and print ErrWidget_A, then call custom behavior
126 | a := ErrWidget_A {Err{5001, timeNow, "test"}}
127 | fmt.Println(a) // fmt will execute Error() method that can have special behavior
128 | fmt.Println("A ErrWidget_A has this error number: ", a.errorNumber())
129 | a.optionalErrHandlingOperation() // Widget_A emails admins
130 |
131 | // Create ErrWidget_B, then call custom behavior
132 | b := ErrWidget_B {Err{6001, timeNow, "test"}}
133 | fmt.Println("A ErrWidget_B has this error number: ", b.errorNumber())
134 | b.optionalErrHandlingOperation() // Widget_B sends SMS message to managers
135 | // Since b was not printed by fmt, the special ErrWidget_B behavior is not triggered
136 | }
137 |
--------------------------------------------------------------------------------
/doubly-linked-list.go:
--------------------------------------------------------------------------------
1 | /*
2 | filename: doubly-linked-list.go
3 | author: Lex Sheehan
4 | copyright: Lex Sheehan LLC
5 | license: GPL
6 | status: published
7 | comments: http://l3x.github.io/golang-code-examples/2014/07/23/doubly-linked-list.html
8 | */
9 | package main
10 | import (
11 | "fmt"
12 | "errors"
13 | "strings"
14 | )
15 | type Value struct {
16 | Name string
17 | MilesAway int
18 | }
19 | type Node struct {
20 | Value // Embedded struct
21 | next, prev *Node
22 | }
23 | type List struct {
24 | head, tail *Node
25 | }
26 | func (l *List) First() *Node {
27 | return l.head
28 | }
29 | func (n *Node) Next() *Node {
30 | return n.next
31 | }
32 | func (n *Node) Prev() *Node {
33 | return n.prev
34 | }
35 | // Create new node with value
36 | func (l *List) Push(v Value) *List {
37 | n := &Node{Value: v}
38 | if l.head == nil {
39 | l.head = n // First node
40 | } else {
41 | l.tail.next = n // Add after prev last node
42 | n.prev = l.tail // Link back to prev last node
43 | }
44 | l.tail = n // reset tail to newly added node
45 | return l
46 | }
47 | func (l *List) Find(name string) *Node {
48 | found := false
49 | var ret *Node = nil
50 | for n := l.First(); n != nil && !found; n = n.Next() {
51 | if n.Value.Name == name {
52 | found = true
53 | ret = n
54 | }
55 | }
56 | return ret
57 | }
58 | func (l *List) Delete(name string) bool {
59 | success := false
60 | node2del := l.Find(name)
61 | if node2del != nil {
62 | fmt.Println("Delete - FOUND: ", name)
63 | prev_node := node2del.prev
64 | next_node := node2del.next
65 | // Remove this node
66 | prev_node.next = node2del.next
67 | next_node.prev = node2del.prev
68 | success = true
69 | }
70 | return success
71 | }
72 | var errEmpty = errors.New("ERROR - List is empty")
73 | // Pop last item from list
74 | func (l *List) Pop() (v Value, err error) {
75 | if l.tail == nil {
76 | err = errEmpty
77 | } else {
78 | v = l.tail.Value
79 | l.tail = l.tail.prev
80 | if l.tail == nil {
81 | l.head = nil
82 | }
83 | }
84 | return v, err
85 | }
86 |
87 | func main() {
88 | dashes := strings.Repeat("-", 50)
89 | l := new(List) // Create Doubly Linked List
90 |
91 | l.Push(Value{Name: "Atlanta", MilesAway: 0})
92 | l.Push(Value{Name: "Las Vegas", MilesAway: 1961})
93 | l.Push(Value{Name: "New York", MilesAway: 881})
94 |
95 | processed := make(map[*Node]bool)
96 |
97 | fmt.Println("First time through list...")
98 | for n := l.First(); n != nil; n = n.Next() {
99 | fmt.Printf("%v\n", n.Value)
100 | if processed[n] {
101 | fmt.Printf("%s as been processed\n", n.Value)
102 | }
103 | processed[n] = true
104 | }
105 | fmt.Println(dashes)
106 | fmt.Println("Second time through list...")
107 | for n := l.First(); n != nil; n = n.Next() {
108 | fmt.Printf("%v", n.Value)
109 | if processed[n] {
110 | fmt.Println(" has been processed")
111 | } else { fmt.Println() }
112 | processed[n] = true
113 | }
114 |
115 | fmt.Println(dashes)
116 | var found_node *Node
117 | city_to_find := "New York"
118 | found_node = l.Find(city_to_find)
119 | if found_node == nil {
120 | fmt.Printf("NOT FOUND: %v\n", city_to_find)
121 | } else {
122 | fmt.Printf("FOUND: %v\n", city_to_find)
123 | }
124 |
125 | city_to_find = "Chicago"
126 | found_node = l.Find(city_to_find)
127 | if found_node == nil {
128 | fmt.Printf("NOT FOUND: %v\n", city_to_find)
129 | } else {
130 | fmt.Printf("FOUND: %v\n", city_to_find)
131 | }
132 |
133 | fmt.Println(dashes)
134 | city_to_remove := "Las Vegas"
135 | successfully_removed_city := l.Delete(city_to_remove)
136 | if successfully_removed_city {
137 | fmt.Printf("REMOVED: %v\n", city_to_remove)
138 | } else {
139 | fmt.Printf("DID NOT REMOVE: %v\n", city_to_remove)
140 | }
141 |
142 | city_to_remove = "Chicago"
143 | successfully_removed_city = l.Delete(city_to_remove)
144 | if successfully_removed_city {
145 | fmt.Printf("REMOVED: %v\n", city_to_remove)
146 | } else {
147 | fmt.Printf("DID NOT REMOVE: %v\n", city_to_remove)
148 | }
149 |
150 | fmt.Println(dashes)
151 | fmt.Println("* Pop each value off list...")
152 | for v, err := l.Pop(); err == nil; v, err = l.Pop() {
153 | fmt.Printf("%v\n", v)
154 | }
155 | fmt.Println(l.Pop()) // Generate error - attempt to pop from empty list
156 | }
157 |
--------------------------------------------------------------------------------
/eclipse-class-filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l3x/golang-code-examples/a752ccf90134637c4226ff7d22e3c73b1e608cc2/eclipse-class-filter.png
--------------------------------------------------------------------------------
/golang-gopher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l3x/golang-code-examples/a752ccf90134637c4226ff7d22e3c73b1e608cc2/golang-gopher.png
--------------------------------------------------------------------------------
/httpserver.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "log"
6 | "errors"
7 | "net/http"
8 | "io/ioutil"
9 | "html/template"
10 | "regexp"
11 | "encoding/json"
12 | "github.com/l3x/jsoncfgo"
13 | "github.com/go-goodies/go_utils"
14 | )
15 |
16 | var Dir string
17 | var Users jsoncfgo.Obj
18 | var AppContext *go_utils.Singleton
19 |
20 | func HtmlFileHandler(response http.ResponseWriter, request *http.Request, filename string){
21 | response.Header().Set("Content-type", "text/html")
22 | webpage, err := ioutil.ReadFile(Dir + filename) // read whole the file
23 | if err != nil {
24 | http.Error(response, fmt.Sprintf("%s file error %v", filename, err), 500)
25 | }
26 | fmt.Fprint(response, string(webpage));
27 | }
28 |
29 | func HelpHandler(response http.ResponseWriter, request *http.Request){
30 | HtmlFileHandler(response, request, "/help.html")
31 | }
32 |
33 | func AjaxHandler(response http.ResponseWriter, request *http.Request){
34 | HtmlFileHandler(response, request, "/ajax.html")
35 | }
36 |
37 | func printCookies(response http.ResponseWriter, request *http.Request) {
38 | cookieNameForUsername := AppContext.Data["CookieNameForUsername"].(string)
39 | fmt.Println("COOKIES:")
40 | for _, cookie := range request.Cookies() {
41 | fmt.Printf("%v: %v\n", cookie.Name, cookie.Value)
42 | if cookie.Name == cookieNameForUsername {
43 | SetUsernameCookie(response, cookie.Value)
44 | }
45 | }; fmt.Println("")
46 | }
47 |
48 | func UserHandler(response http.ResponseWriter, request *http.Request){
49 | response.Header().Set("Content-type", "application/json")
50 | // json data to send to client
51 | data := map[string]string { "api" : "user", "name" : "" }
52 | userApiURL := regexp.MustCompile(`^/user/(\w+)$`)
53 | usernameMatches := userApiURL.FindStringSubmatch(request.URL.Path)
54 | // regex matches example: ["/user/joesample", "joesample"]
55 | if len(usernameMatches) > 0 {
56 | printCookies(response, request)
57 | var userName string
58 | userName = usernameMatches[1] // ex: joesample
59 | userObj := AppContext.Data[userName]
60 | fmt.Printf("userObj: %v\n", userObj)
61 | if userObj == nil {
62 | msg := fmt.Sprintf("Invalid username (%s)", userName)
63 | panic(errors.New(msg))
64 | } else {
65 | // Send JSON to the client
66 | thisUser := userObj.(jsoncfgo.Obj)
67 | fmt.Printf("thisUser: %v\n", thisUser)
68 | data["name"] = thisUser["firstname"].(string) + " " + thisUser["lastname"].(string)
69 | }
70 | json_bytes, _ := json.Marshal(data)
71 | fmt.Printf("json_bytes: %s\n", string(json_bytes[:]))
72 | fmt.Fprintf(response, "%s\n", json_bytes)
73 |
74 | } else {
75 | http.Error(response, "404 page not found", 404)
76 | }
77 | }
78 |
79 | func SetUsernameCookie(response http.ResponseWriter, userName string){
80 | // Add cookie to response
81 | cookieName := AppContext.Data["CookieNameForUsername"].(string)
82 | cookie := http.Cookie{Name: cookieName, Value: userName}
83 | http.SetCookie(response, &cookie)
84 | }
85 |
86 | func DebugFormHandler(response http.ResponseWriter, request *http.Request){
87 |
88 | printCookies(response, request)
89 |
90 | err := request.ParseForm() // Parse URL and POST data into request.Form
91 | if err != nil {
92 | http.Error(response, fmt.Sprintf("error parsing url %v", err), 500)
93 | }
94 |
95 | // Set cookie and MIME type in the HTTP headers.
96 | fmt.Printf("request.Form: %v\n", request.Form)
97 | if request.Form["username"] != nil {
98 | cookieVal := request.Form["username"][0]
99 | fmt.Printf("cookieVal: %s\n", cookieVal)
100 | SetUsernameCookie(response, cookieVal)
101 | }; fmt.Println("")
102 |
103 | templateHandler(response, request)
104 | response.Header().Set("Content-type", "text/plain")
105 |
106 | // Send debug diagnostics to client
107 | fmt.Fprintf(response, "")
108 | fmt.Fprintf(response, "request.Method | '%v' |
", request.Method)
109 | fmt.Fprintf(response, "request.RequestURI | '%v' |
", request.RequestURI)
110 | fmt.Fprintf(response, "request.URL.Path | '%v' |
", request.URL.Path)
111 | fmt.Fprintf(response, "request.Form | '%v' |
", request.Form)
112 | fmt.Fprintf(response, "request.Cookies() | '%v' |
", request.Cookies())
113 | fmt.Fprintf(response, "
")
114 |
115 | }
116 |
117 | func DebugQueryHandler(response http.ResponseWriter, request *http.Request){
118 |
119 | // Set cookie and MIME type in the HTTP headers.
120 | response.Header().Set("Content-type", "text/plain")
121 |
122 | // Parse URL and POST data into the request.Form
123 | err := request.ParseForm()
124 | if err != nil {
125 | http.Error(response, fmt.Sprintf("error parsing url %v", err), 500)
126 | }
127 |
128 | // Send debug diagnostics to client
129 | fmt.Fprintf(response, " request.Method '%v'\n", request.Method)
130 | fmt.Fprintf(response, " request.RequestURI '%v'\n", request.RequestURI)
131 | fmt.Fprintf(response, " request.URL.Path '%v'\n", request.URL.Path)
132 | fmt.Fprintf(response, " request.Form '%v'\n", request.Form)
133 | fmt.Fprintf(response, " request.Cookies() '%v'\n", request.Cookies())
134 | }
135 |
136 | func templateHandler(w http.ResponseWriter, r *http.Request) {
137 | t, _ := template.New("form.html").Parse(form)
138 | t.Execute(w, "")
139 | }
140 |
141 | func formHandler(w http.ResponseWriter, r *http.Request) {
142 | log.Println(r.Form)
143 | templateHandler(w, r)
144 | }
145 |
146 | var form = `
147 | Debug Info (POST form)
148 |
156 |
157 |
158 | `
159 |
160 | func errorHandler(f func(http.ResponseWriter, *http.Request) error) http.HandlerFunc {
161 | return func(w http.ResponseWriter, r *http.Request) {
162 | log.Println("errorHandler...")
163 | err := f(w, r)
164 | if err != nil {
165 | http.Error(w, err.Error(), http.StatusInternalServerError)
166 | log.Printf("handling %q: %v", r.RequestURI, err)
167 | }
168 | }
169 | }
170 |
171 | func doThis() error { return nil }
172 | func doThat() error { return errors.New("ERROR - doThat") }
173 |
174 | func wrappedHandler(w http.ResponseWriter, r *http.Request) error {
175 | log.Println("betterHandler...")
176 | if err := doThis(); err != nil {
177 | return fmt.Errorf("doing this: %v", err)
178 | }
179 |
180 | if err := doThat(); err != nil {
181 | return fmt.Errorf("doing that: %v", err)
182 | }
183 | return nil
184 | }
185 |
186 |
187 | func main() {
188 | cfg := jsoncfgo.Load("/Users/lex/dev/go/data/webserver/webserver-config.json")
189 |
190 | host := cfg.OptionalString("host", "localhost")
191 | fmt.Printf("host: %v\n", host)
192 |
193 | port := cfg.OptionalInt("port", 8080)
194 | fmt.Printf("port: %v\n", port)
195 |
196 | Dir = cfg.OptionalString("dir", "www/")
197 | fmt.Printf("web_dir: %v\n", Dir)
198 |
199 | redirect_code := cfg.OptionalInt("redirect_code", 307)
200 | fmt.Printf("redirect_code: %v\n\n", redirect_code)
201 |
202 | mux := http.NewServeMux()
203 |
204 | fileServer := http.Dir(Dir)
205 | fileHandler := http.FileServer(fileServer)
206 | mux.Handle("/", fileHandler)
207 |
208 | rdh := http.RedirectHandler("http://example.org", redirect_code)
209 | mux.Handle("/redirect", rdh)
210 | mux.Handle("/notFound", http.NotFoundHandler())
211 |
212 | mux.Handle("/help", http.HandlerFunc( HelpHandler ))
213 |
214 | mux.Handle("/debugForm", http.HandlerFunc( DebugFormHandler ))
215 | mux.Handle("/debugQuery", http.HandlerFunc( DebugQueryHandler ))
216 |
217 | mux.Handle("/user/", http.HandlerFunc( UserHandler ))
218 | mux.Handle("/ajax", http.HandlerFunc( AjaxHandler ))
219 |
220 | mux.Handle("/adapter", errorHandler(wrappedHandler))
221 |
222 | log.Printf("Running on port %d\n", port)
223 |
224 | addr := fmt.Sprintf("%s:%d", host, port)
225 |
226 | Users := jsoncfgo.Load("/Users/lex/dev/go/data/webserver/users.json")
227 |
228 | joesample := Users.OptionalObject("joesample")
229 | fmt.Printf("joesample: %v\n", joesample)
230 | fmt.Printf("joesample['firstname']: %v\n", joesample["firstname"])
231 | fmt.Printf("joesample['lastname']: %v\n\n", joesample["lastname"])
232 |
233 | alicesmith := Users.OptionalObject("alicesmith")
234 | fmt.Printf("alicesmith: %v\n", alicesmith)
235 | fmt.Printf("alicesmith['firstname']: %v\n", alicesmith["firstname"])
236 | fmt.Printf("alicesmith['lastname']: %v\n\n", alicesmith["lastname"])
237 |
238 | bobbrown := Users.OptionalObject("bobbrown")
239 | fmt.Printf("bobbrown: %v\n", bobbrown)
240 | fmt.Printf("bobbrown['firstname']: %v\n", bobbrown["firstname"])
241 | fmt.Printf("bobbrown['lastname']: %v\n\n", bobbrown["lastname"])
242 |
243 | AppContext = go_oops.NewSingleton()
244 | AppContext.Data["CookieNameForUsername"] = "testapp-username"
245 | AppContext.Data["joesample"] = joesample
246 | AppContext.Data["alicesmith"] = alicesmith
247 | AppContext.Data["bobbrown"] = bobbrown
248 | fmt.Printf("AppContext: %v\n", AppContext)
249 | fmt.Printf("AppContext.Data[\"joesample\"]: %v\n", AppContext.Data["joesample"])
250 | fmt.Printf("AppContext.Data[\"alicesmith\"]: %v\n", AppContext.Data["alicesmith"])
251 | fmt.Printf("AppContext.Data[\"bobbrown\"]: %v\n\n", AppContext.Data["bobbrown"])
252 |
253 | err := http.ListenAndServe(addr, mux)
254 | fmt.Println(err.Error())
255 | }
256 |
--------------------------------------------------------------------------------
/images/cedar-tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l3x/golang-code-examples/a752ccf90134637c4226ff7d22e3c73b1e608cc2/images/cedar-tree.png
--------------------------------------------------------------------------------
/jsoncfgo-a-json-config-file-reader.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "time"
6 | "log"
7 | "github.com/l3x/jsoncfgo"
8 | )
9 |
10 | func main() {
11 |
12 | cfg := jsoncfgo.Load("/Users/lex/dev/go/data/jsoncfgo/simple-config.json")
13 |
14 | host := cfg.String("host")
15 | fmt.Printf("host: %v\n", host)
16 | bogusHost := cfg.String("bogusHost", "default_host_name")
17 | fmt.Printf("host: %v\n\n", bogusHost)
18 |
19 | port := cfg.Int("port")
20 | fmt.Printf("port: %v\n", port)
21 | bogusPort := cfg.Int("bogusPort", 9000)
22 | fmt.Printf("bogusPort: %v\n\n", bogusPort)
23 |
24 | bigNumber := cfg.Int64("bignNumber")
25 | fmt.Printf("bigNumber: %v\n", bigNumber)
26 | bogusBigNumber := cfg.Int64("bogusBigNumber", 9000000000000000000)
27 | fmt.Printf("bogusBigNumber: %v\n\n", bogusBigNumber)
28 |
29 | active := cfg.Bool("active")
30 | fmt.Printf("active: %v\n", active)
31 | bogusFalseActive := cfg.Bool("bogusFalseActive", false)
32 | fmt.Printf("bogusFalseActive: %v\n", bogusFalseActive)
33 | bogusTrueActive := cfg.Bool("bogusTrueActive", true)
34 | fmt.Printf("bogusTrueActive: %v\n\n", bogusTrueActive)
35 |
36 | appList := cfg.List("appList")
37 | fmt.Printf("appList: %v\n", appList)
38 | bogusAppList := cfg.List("bogusAppList", []string{"app1", "app2", "app3"})
39 | fmt.Printf("bogusAppList: %v\n\n", bogusAppList)
40 |
41 | numbers := cfg.IntList("numbers")
42 | fmt.Printf("numbers: %v\n", numbers)
43 | bogusSettings := cfg.IntList("bogusSettings", []int64{1, 2, 3})
44 | fmt.Printf("bogusAppList: %v\n\n", bogusSettings)
45 |
46 | if err := cfg.Validate(); err != nil {
47 | time.Sleep(100 * time.Millisecond)
48 | defer log.Fatalf("ERROR - Invalid config file...\n%v", err)
49 | return
50 | }
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/map-of-car-options.go:
--------------------------------------------------------------------------------
1 | /*
2 | filename: map-of-car-options.go
3 | author: Lex Sheehan
4 | copyright: Lex Sheehan LLC
5 | license: GPL
6 | status: published
7 | comments: http://l3x.github.io/golang-code-examples/2014/07/22/map-of-car-options.html
8 | */
9 | package main
10 |
11 | import (
12 | "fmt"
13 | "strings"
14 | )
15 |
16 | type Car struct {
17 | Make string
18 | Model string
19 | Options []string
20 | }
21 |
22 | func main() {
23 |
24 | dashes := strings.Repeat("-", 50)
25 |
26 | is250 := &Car{"Lexus", "IS250", []string{"GPS", "Alloy Wheels", "Roof Rack", "Power Outlets", "Heated Seats"}}
27 | accord := &Car{"Honda", "Accord", []string{"Alloy Wheels", "Roof Rack"}}
28 | blazer := &Car{"Chevy", "Blazer", []string{"GPS", "Roof Rack", "Power Outlets"}}
29 |
30 | cars := []*Car{is250, accord, blazer}
31 | fmt.Printf("Cars:\n%v\n\n", cars) // cars is a slice of pointers to our three cars
32 |
33 | // Create a map to associate options with each car
34 | car_options := make(map[string][]*Car)
35 |
36 | fmt.Printf("CARS:\n%s\n", dashes)
37 | for _, car := range cars {
38 | fmt.Printf("%v\n", car)
39 | for _, option := range car.Options {
40 | // Associate this car with each of it's options
41 | car_options[option] = append(car_options[option], car)
42 | fmt.Printf("car_options[option]: %s\n", option)
43 | }
44 | fmt.Println(dashes)
45 | }
46 | fmt.Println(dashes)
47 |
48 | // Print a list of cars with the "GPS" option
49 | for _, p := range car_options["GPS"] {
50 | fmt.Println(p.Make, "has GPS.")
51 | }
52 |
53 | fmt.Println("")
54 | fmt.Println(len(car_options["Alloy Wheels"]), "has Alloy Wheels.")
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/polymorphic_shapes.go:
--------------------------------------------------------------------------------
1 | /*
2 | filename: polymorphic_shapes.go
3 | author: Lex Sheehan
4 | copyright: Lex Sheehan LLC
5 | license: GPL
6 | status: published
7 | comments: http://l3x.github.io/golang-code-examples/2014/07/14/custom-error-handling.html
8 | */
9 | package main // Executable commands must always use package main.
10 |
11 | import (
12 | "fmt" // fmt.Println formats output to console
13 | "math" // provides math.Sqrt function
14 | )
15 |
16 | // ----------------------
17 | // Shape interface
18 | // ----------------------
19 | // Shape interface defines a method set (consisting of the area method)
20 | type Shape interface {
21 | area() float64 // any type that implements an area method is considered a Shape
22 | }
23 | // Calculate total area of all shapes via polymorphism (all shapes implement the area method)
24 | func totalArea(shapes ...Shape) float64 { // Use interface type as as function argument
25 | var area float64 // "..." makes shapes "variadic" (can send one or more)
26 | for _, s := range shapes {
27 | area += s.area() // the current Shape implements/receives the area method
28 | } // go passes the pointer to the shape to the area method
29 | return area
30 | }
31 |
32 | // ----------------------
33 | // Drawer interface
34 | // ----------------------
35 | type Drawer interface {
36 | draw() // does not return a type
37 | }
38 | func drawShape(d Drawer) { // associate this method with the Drawer interface
39 | d.draw()
40 | }
41 |
42 | // ----------------------
43 | // Circle Type
44 | // ----------------------
45 | type Circle struct { // Since "Circle" is capitalized, it is visible outside this package
46 | x, y, r float64 // a Circle struct is a collection of fields: x, y, r
47 | }
48 | // Circle implements Shape interface b/c it has an area method
49 | // area is a method, which is special type of function that is associated with the Circle struct
50 | // The Circle struct becomes the "receiver" of this method, so we can use the "." operator
51 | func (c *Circle) area() float64 { // dereference Circle type (data pointed to by c)
52 | return math.Pi * c.r * c.r // Pi is a constant in the math package
53 | }
54 | func (c Circle) draw() {
55 | fmt.Println("Circle drawing with radius: ", c.r) // encapsulated draw implementation for Circle type
56 | }
57 | // ----------------------
58 | // Rectangle Type
59 | // ----------------------
60 | type Rectangle struct { // a struct contains named fields of data
61 | x1, y1, x2, y2 float64 // define multiple fields with same data type on one line
62 | }
63 | func distance(x1, y1, x2, y2 float64) float64 { // lowercase functin name visible only in this package
64 | a := x2 - x1
65 | b := y2 - y1
66 | return math.Sqrt(a * a + b * b)
67 | }
68 | // Rectangle implements Shape interface b/c it has an area method
69 | func (r *Rectangle) area() float64 {
70 | l := distance(r.x1, r.y1, r.x1, r.y2) // define and assign local variable "l"
71 | w := distance(r.x1, r.y1, r.x2, r.y1) // l and w only available within scope of area function
72 | return l * w
73 | }
74 | func (r Rectangle) draw() {
75 | fmt.Printf("Rectangle drawing with point1: (%f, %f) and point2: (%f, %f)\n", r.x1, r.y1, r.x2, r.y2)
76 | }
77 | // ----------------------
78 | // MultiShape Type
79 | // ----------------------
80 | type MultiShape struct {
81 | shapes []Shape // shapes field is a slice of interfaces
82 | }
83 | //
84 | func (m *MultiShape) area() float64 {
85 | var area float64
86 | for _, shape := range m.shapes { // iterate through shapes ("_" indicates that index is not used)
87 | area += shape.area() // execute polymorphic area method for this shape
88 | }
89 | return area
90 | }
91 |
92 | func main() {
93 | c := Circle{0, 0, 5} // initialize new instance of Circle type by field order "struct literal"
94 | // The new function allocates memory for all fields, sets each to their zero value and returns a pointer
95 | c2 := new(Circle) // c2 is a pointer to the instantiated Circle type
96 | c2.x = 0; c2.y = 0; c2.r = 10 // initialize data with multiple statements on one line
97 | fmt.Println("Circle Area:", totalArea(&c)) // pass address of circle (c)
98 | fmt.Println("Circle2 Area:", totalArea(c2)) // c2 was defined using built-in new function
99 | r := Rectangle{x1: 0, y1: 0, x2: 5, y2: 5} // "struct literal" rectangle (r) initialized by field name
100 | fmt.Println("Rectangle Area:", totalArea(&r)) // pass address of rectangle (r)
101 | fmt.Println("Rectangle + Circle Area:", totalArea(&c, c2, &r)) // can pass multiple shapes
102 | m := MultiShape{[]Shape{&r, &c, c2}} // pass slice of shapes
103 | fmt.Println("Multishape Area:", totalArea(&m)) // calculate total area of all shapes
104 | fmt.Println("Area Totals:", totalArea(&c, c2, &r)) // c2 is a pointer to a circle, &c and &r are addresses of shapes
105 | fmt.Println("2 X Area Totals:", totalArea(&c, c2, &r, &m)) // twice the size of all areas
106 | drawShape(c) // execute polymorphic method call
107 | drawShape(c2)
108 | drawShape(r)
109 | }
110 |
--------------------------------------------------------------------------------
/pta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/l3x/golang-code-examples/a752ccf90134637c4226ff7d22e3c73b1e608cc2/pta.png
--------------------------------------------------------------------------------
/www/ajax.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | go server example
6 |
7 |
8 |
9 |
10 |
34 |
35 |
36 | Ajax Example
37 |
38 |
39 | The user's full name is: ?
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/www/form.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | go web server example
6 |
7 |
8 |
9 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/www/help.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | go web server example
6 |
9 |
10 |
11 | go web server example
12 |
13 | Help (this page)
14 | File Server (dir value from config file)
15 | Redirect (to example.com)
16 | NotFound Handler (should get a 404 error)
17 | Debug Info (POST form)
18 | Debug Info (GET request)
19 | Ajax Callback
20 | Function Adapter
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/www/test1.html:
--------------------------------------------------------------------------------
1 | one
2 |
--------------------------------------------------------------------------------
/www/test2.html:
--------------------------------------------------------------------------------
1 | two
2 |
--------------------------------------------------------------------------------