GO by example, part 5
This commit is contained in:
parent
5d7e654fa1
commit
a7d96f5106
26
5-go-by-example/41-sorting.go
Normal file
26
5-go-by-example/41-sorting.go
Normal file
@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Go’s sort package implements sorting for builtins and user-defined types
|
||||
func main() {
|
||||
// Sort methods are specific to the builtin type
|
||||
|
||||
// an example for strings
|
||||
// sorting is in-place, so it changes the given slice and doesn’t return a new one
|
||||
strs := []string{"c", "a", "b"}
|
||||
sort.Strings(strs)
|
||||
fmt.Println("Strings:", strs)
|
||||
|
||||
// an example of sorting ints
|
||||
ints := []int{7, 2, 4}
|
||||
sort.Ints(ints)
|
||||
fmt.Println("Ints: ", ints)
|
||||
|
||||
// use sort to check if a slice is already in sorted order
|
||||
s := sort.IntsAreSorted(ints)
|
||||
fmt.Println("Sorted: ", s)
|
||||
}
|
27
5-go-by-example/42-sorting-by-functions.go
Normal file
27
5-go-by-example/42-sorting-by-functions.go
Normal file
@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// in order to sort by a custom function in Go, you need a corresponding type
|
||||
type byLength []string
|
||||
|
||||
// implement sort.Interface - Len, Less, and Swap - on the type
|
||||
func (s byLength) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
func (s byLength) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
func (s byLength) Less(i, j int) bool {
|
||||
return len(s[i]) < len(s[j])
|
||||
}
|
||||
|
||||
func main() {
|
||||
// implement the custom sort by converting the original fruits slice to byLength and then use sort
|
||||
fruits := []string{"peach", "banana", "kiwi"}
|
||||
sort.Sort(byLength(fruits))
|
||||
fmt.Println(fruits)
|
||||
}
|
16
5-go-by-example/43-panic.go
Normal file
16
5-go-by-example/43-panic.go
Normal file
@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import "os"
|
||||
|
||||
// a panic typically means something went unexpectedly wrong
|
||||
func main() {
|
||||
|
||||
// this is the only code here designed to panic
|
||||
panic("a problem")
|
||||
|
||||
// a common use of panic is to abort if a function returns an error value that one doesn’t know how to handle
|
||||
_, err := os.Create("/tmp/file")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
42
5-go-by-example/44-defer.go
Normal file
42
5-go-by-example/44-defer.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Defer is used to ensure that a function call is performed later in a program’s execution, usually for purposes of cleanup
|
||||
func main() {
|
||||
// suppose you wanted to create a file, write to it, and then close when done
|
||||
// immediately after getting a file object with createFile, defer the closing of that file with closeFile
|
||||
// this will be executed at the end of the enclosing function (main), after writeFile has finished
|
||||
f := createFile("/tmp/defer.txt")
|
||||
defer closeFile(f)
|
||||
writeFile(f)
|
||||
}
|
||||
|
||||
func createFile(p string) *os.File {
|
||||
fmt.Println("creating")
|
||||
f, err := os.Create(p)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func writeFile(f *os.File) {
|
||||
fmt.Println("writing")
|
||||
fmt.Fprintln(f, "data")
|
||||
|
||||
}
|
||||
|
||||
// it’s important to check for errors when closing a file, even in a deferred function
|
||||
func closeFile(f *os.File) {
|
||||
fmt.Println("closing")
|
||||
err := f.Close()
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
27
5-go-by-example/45-recover.go
Normal file
27
5-go-by-example/45-recover.go
Normal file
@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// this function panics
|
||||
func mayPanic() {
|
||||
panic("a problem")
|
||||
}
|
||||
|
||||
// it is possible to recover from a panic, by using the recover built-in function
|
||||
func main() {
|
||||
|
||||
// recover must be called within a deferred function
|
||||
// when the enclosing function panics, the defer will activate and a recover call within it will catch the panic
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
// the return value of recover is the error raised in the call to panic
|
||||
fmt.Println("Recovered. Error:\n", r)
|
||||
}
|
||||
}()
|
||||
|
||||
mayPanic()
|
||||
|
||||
// this code will not run, because mayPanic panics
|
||||
// the execution of main stops at the point of the panic and resumes in the deferred closure
|
||||
fmt.Println("After mayPanic()")
|
||||
}
|
87
5-go-by-example/46-collection-function.go
Normal file
87
5-go-by-example/46-collection-function.go
Normal file
@ -0,0 +1,87 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// in Go it’s common to provide collection functions if and when they are specifically needed for your program and data types
|
||||
|
||||
// Index returns the first index of the target string t, or -1 if no match is found
|
||||
func Index(vs []string, t string) int {
|
||||
for i, v := range vs {
|
||||
if v == t {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// Include returns true if the target string t is in the slice
|
||||
func Include(vs []string, t string) bool {
|
||||
return Index(vs, t) >= 0
|
||||
}
|
||||
|
||||
// Any returns true if one of the strings in the slice satisfies the predicate f
|
||||
func Any(vs []string, f func(string) bool) bool {
|
||||
for _, v := range vs {
|
||||
if f(v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// All returns true if all of the strings in the slice satisfy the predicate f
|
||||
func All(vs []string, f func(string) bool) bool {
|
||||
for _, v := range vs {
|
||||
if !f(v) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Filter returns a new slice containing all strings in the slice that satisfy the predicate f
|
||||
func Filter(vs []string, f func(string) bool) []string {
|
||||
vsf := make([]string, 0)
|
||||
for _, v := range vs {
|
||||
if f(v) {
|
||||
vsf = append(vsf, v)
|
||||
}
|
||||
}
|
||||
return vsf
|
||||
}
|
||||
|
||||
// Map returns a new slice containing the results of applying the function f to each string in the original slice
|
||||
func Map(vs []string, f func(string) string) []string {
|
||||
vsm := make([]string, len(vs))
|
||||
for i, v := range vs {
|
||||
vsm[i] = f(v)
|
||||
}
|
||||
return vsm
|
||||
}
|
||||
|
||||
func main() {
|
||||
// try out various collection functions
|
||||
var strs = []string{"peach", "apple", "pear", "plum"}
|
||||
|
||||
fmt.Println(Index(strs, "pear"))
|
||||
|
||||
fmt.Println(Include(strs, "grape"))
|
||||
|
||||
fmt.Println(Any(strs, func(v string) bool {
|
||||
return strings.HasPrefix(v, "p")
|
||||
}))
|
||||
|
||||
fmt.Println(All(strs, func(v string) bool {
|
||||
return strings.HasPrefix(v, "p")
|
||||
}))
|
||||
|
||||
fmt.Println(Filter(strs, func(v string) bool {
|
||||
return strings.Contains(v, "e")
|
||||
}))
|
||||
|
||||
fmt.Println(Map(strs, strings.ToUpper))
|
||||
|
||||
}
|
31
5-go-by-example/47-string-functions.go
Normal file
31
5-go-by-example/47-string-functions.go
Normal file
@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
s "strings"
|
||||
)
|
||||
|
||||
// alias fmt.Println to a shorter name
|
||||
var p = fmt.Println
|
||||
|
||||
// standard library’s strings package provides many useful string-related functions
|
||||
func main() {
|
||||
// sample of the functions available in strings
|
||||
p("Contains: ", s.Contains("test", "es"))
|
||||
p("Count: ", s.Count("test", "t"))
|
||||
p("HasPrefix: ", s.HasPrefix("test", "te"))
|
||||
p("HasSuffix: ", s.HasSuffix("test", "st"))
|
||||
p("Index: ", s.Index("test", "e"))
|
||||
p("Join: ", s.Join([]string{"a", "b"}, "-"))
|
||||
p("Repeat: ", s.Repeat("a", 5))
|
||||
p("Replace: ", s.Replace("foo", "o", "0", -1))
|
||||
p("Replace: ", s.Replace("foo", "o", "0", 1))
|
||||
p("Split: ", s.Split("a-b-c-d-e", "-"))
|
||||
p("ToLower: ", s.ToLower("TEST"))
|
||||
p("ToUpper: ", s.ToUpper("test"))
|
||||
p()
|
||||
|
||||
// not part of strings
|
||||
p("Len: ", len("hello"))
|
||||
p("Char:", "hello"[1])
|
||||
}
|
82
5-go-by-example/48-string-.formatting.go
Normal file
82
5-go-by-example/48-string-.formatting.go
Normal file
@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
type point struct {
|
||||
x, y int
|
||||
}
|
||||
|
||||
// common string formatting tasks
|
||||
func main() {
|
||||
// prints an instance of point struct
|
||||
p := point{1, 2}
|
||||
fmt.Printf("struct1: %v\n", p)
|
||||
|
||||
// the %+v variant will include the struct’s field names
|
||||
fmt.Printf("struct2: %+v\n", p)
|
||||
|
||||
// the %#v variant prints a Go syntax representation of the value
|
||||
fmt.Printf("struct3: %#v\n", p)
|
||||
|
||||
// the %T variant prints the type of a value
|
||||
fmt.Printf("type: %T\n", p)
|
||||
|
||||
// formatting booleans straight-forward
|
||||
fmt.Printf("bool: %t\n", true)
|
||||
|
||||
// use %d for standard, base-10 formatting
|
||||
fmt.Printf("int: %d\n", 123)
|
||||
|
||||
// prints a binary representation
|
||||
fmt.Printf("bin: %b\n", 14)
|
||||
|
||||
// prints the character corresponding to the given integer
|
||||
fmt.Printf("char: %c\n", 33)
|
||||
|
||||
// %x provides hex encoding
|
||||
fmt.Printf("hex: %x\n", 456)
|
||||
|
||||
// decimal formatting use %f
|
||||
fmt.Printf("float1: %f\n", 78.9)
|
||||
|
||||
// %e and %E format the float in (different versions of) scientific notation
|
||||
fmt.Printf("float2: %e\n", 123400000.0)
|
||||
fmt.Printf("float3: %E\n", 123400000.0)
|
||||
|
||||
// basic string printing use %s
|
||||
fmt.Printf("str1: %s\n", "\"string\"")
|
||||
|
||||
// to double-quote strings use %q
|
||||
fmt.Printf("str2: %q\n", "\"string\"")
|
||||
|
||||
// %x renders the string in base-16, with two output characters per byte of input
|
||||
fmt.Printf("str3: %x\n", "hex this")
|
||||
|
||||
// use %p to print a representation of a pointer
|
||||
fmt.Printf("pointer: %p\n", &p)
|
||||
|
||||
// to specify the width of an integer, use a number after the % in the verb
|
||||
fmt.Printf("width1: |%6d|%6d|\n", 12, 345)
|
||||
|
||||
// to specify the width of printed floats
|
||||
fmt.Printf("width2: |%6.2f|%6.2f|\n", 1.2, 3.45)
|
||||
|
||||
// to left-justify, use the - flag
|
||||
fmt.Printf("width3: |%-6.2f|%-6.2f|\n", 1.2, 3.45)
|
||||
|
||||
// specify width when formatting strings
|
||||
fmt.Printf("width4: |%6s|%6s|\n", "foo", "b")
|
||||
|
||||
// and left-justify strings with - too
|
||||
fmt.Printf("width5: |%-6s|%-6s|\n", "foo", "b")
|
||||
|
||||
// Sprintf formats and returns a string without printing it anywhere
|
||||
s := fmt.Sprintf("sprintf: a %s", "string")
|
||||
fmt.Println(s)
|
||||
|
||||
// format+print to io.Writers other than os.Stdout using Fprintf
|
||||
fmt.Fprintf(os.Stderr, "io: an %s\n", "error")
|
||||
}
|
57
5-go-by-example/49-regex.go
Normal file
57
5-go-by-example/49-regex.go
Normal file
@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// Go offers built-in support for regular expressions
|
||||
func main() {
|
||||
// test whether a pattern matches a string
|
||||
match, _ := regexp.MatchString("p([a-z]+)ch", "peach")
|
||||
fmt.Println(match)
|
||||
|
||||
// compile an optimized Regexp struct
|
||||
r, _ := regexp.Compile("p([a-z]+)ch")
|
||||
|
||||
// match test like earlier
|
||||
fmt.Println(r.MatchString("peach"))
|
||||
|
||||
// finds the match for the regex
|
||||
fmt.Println(r.FindString("peach punch"))
|
||||
|
||||
// finds the first match but returns the start and end indexes for the match instead of the matching text
|
||||
fmt.Println("idx:", r.FindStringIndex("peach punch"))
|
||||
|
||||
// include information about both the whole-pattern matches and the submatches within those matches
|
||||
fmt.Println(r.FindStringSubmatch("peach punch"))
|
||||
|
||||
// information about the indexes of matches and submatches
|
||||
fmt.Println(r.FindStringSubmatchIndex("peach punch"))
|
||||
|
||||
// apply to all matches in the input, not just the first
|
||||
fmt.Println(r.FindAllString("peach punch pinch", -1))
|
||||
|
||||
// the All variants are available for the other functions too
|
||||
fmt.Println("all:", r.FindAllStringSubmatchIndex(
|
||||
"peach punch pinch", -1))
|
||||
|
||||
// providing a non-negative integer as the second argument to these functions will limit the number of matches
|
||||
fmt.Println(r.FindAllString("peach punch pinch", 2))
|
||||
|
||||
// provide []byte arguments and drop String from the function name
|
||||
fmt.Println(r.Match([]byte("peach")))
|
||||
|
||||
// MustCompile panics instead of returning an error, which makes it safer to use for global variables
|
||||
r = regexp.MustCompile("p([a-z]+)ch")
|
||||
fmt.Println("regexp:", r)
|
||||
|
||||
// replace subsets of strings with other values
|
||||
fmt.Println(r.ReplaceAllString("a peach", "<fruit>"))
|
||||
|
||||
// transform matched text with a given functions
|
||||
in := []byte("a peach")
|
||||
out := r.ReplaceAllFunc(in, bytes.ToUpper)
|
||||
fmt.Println(string(out))
|
||||
}
|
93
5-go-by-example/50-json.go
Normal file
93
5-go-by-example/50-json.go
Normal file
@ -0,0 +1,93 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// demonstrate encoding and decoding of custom types below
|
||||
type response1 struct {
|
||||
Page int
|
||||
Fruits []string
|
||||
}
|
||||
|
||||
// only exported fields will be encoded/decoded in JSON
|
||||
// Fields must start with capital letters to be exported
|
||||
type response2 struct {
|
||||
Page int `json:"page"`
|
||||
Fruits []string `json:"fruits"`
|
||||
}
|
||||
|
||||
// Go offers built-in support for JSON encoding and decoding, including to and from built-in and custom data types
|
||||
func main() {
|
||||
// encoding basic data types to JSON strings
|
||||
bolB, _ := json.Marshal(true)
|
||||
fmt.Println(string(bolB))
|
||||
|
||||
intB, _ := json.Marshal(1)
|
||||
fmt.Println(string(intB))
|
||||
|
||||
fltB, _ := json.Marshal(2.34)
|
||||
fmt.Println(string(fltB))
|
||||
|
||||
strB, _ := json.Marshal("gopher")
|
||||
fmt.Println(string(strB))
|
||||
|
||||
// some for slices and maps, which encode to JSON arrays and objects
|
||||
slcD := []string{"apple", "peach", "pear"}
|
||||
slcB, _ := json.Marshal(slcD)
|
||||
fmt.Println(string(slcB))
|
||||
|
||||
mapD := map[string]int{"apple": 5, "lettuce": 7}
|
||||
mapB, _ := json.Marshal(mapD)
|
||||
fmt.Println(string(mapB))
|
||||
|
||||
// the JSON package can automatically encode your custom data types
|
||||
// it will only include exported fields in the encoded output and will by default use those names as the JSON keys
|
||||
res1D := &response1{
|
||||
Page: 1,
|
||||
Fruits: []string{"apple", "peach", "pear"}}
|
||||
res1B, _ := json.Marshal(res1D)
|
||||
fmt.Println(string(res1B))
|
||||
|
||||
// use tags on struct field declarations to customize the encoded JSON key names
|
||||
res2D := &response2{
|
||||
Page: 1,
|
||||
Fruits: []string{"apple", "peach", "pear"}}
|
||||
res2B, _ := json.Marshal(res2D)
|
||||
fmt.Println(string(res2B))
|
||||
|
||||
// generic decoding JSON data into Go values
|
||||
byt := []byte(`{"num":6.13,"strs":["a","b"]}`)
|
||||
|
||||
// provide a variable where the JSON package can put the decoded data
|
||||
var dat map[string]interface{}
|
||||
|
||||
// actual decoding, and a check for associated errors
|
||||
if err := json.Unmarshal(byt, &dat); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(dat)
|
||||
|
||||
// in order to use the values in the decoded map, convert them to their appropriate type
|
||||
num := dat["num"].(float64)
|
||||
fmt.Println(num)
|
||||
|
||||
// accessing nested data requires a series of conversions
|
||||
strs := dat["strs"].([]interface{})
|
||||
str1 := strs[0].(string)
|
||||
fmt.Println(str1)
|
||||
|
||||
// decode JSON into custom data types
|
||||
str := `{"page": 1, "fruits": ["apple", "peach"]}`
|
||||
res := response2{}
|
||||
json.Unmarshal([]byte(str), &res)
|
||||
fmt.Println(res)
|
||||
fmt.Println(res.Fruits[0])
|
||||
|
||||
// stream JSON encodings directly to os.Writers
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
d := map[string]int{"apple": 5, "lettuce": 7}
|
||||
enc.Encode(d)
|
||||
}
|
Loading…
Reference in New Issue
Block a user