go编程之常见工具函数
1、时间格式化
基于模式的布局进行时间格式化和解析
1 package main 2 3 import "fmt" 4 import "time" 5 6 func main() { 7 p := fmt.Println 8 9 t := time.Now() 10 p(t.Format(time.RFC3339)) 11 12 t1, e := time.Parse( 13 time.RFC3339, 14 "2012-11-01T22:08:41+00:00") 15 p(t1) 16 17 p(t.Format("3:04PM")) 18 p(t.Format("Mon Jan _2 15:04:05 2006")) 19 p(t.Format("2006-01-02T15:04:05.999999-07:00")) 20 form := "3 04 PM" 21 t2, e := time.Parse(form, "8 41 PM") 22 p(t2) 23 24 fmt.Printf("%d-%02d-%02dT%02d:%02d:%02d-00:00\n", 25 t.Year(), t.Month(), t.Day(), 26 t.Hour(), t.Minute(), t.Second()) 27 28 ansic := "Mon Jan _2 15:04:05 2006" 29 _, e = time.Parse(ansic, "8:41PM") 30 p(e) 31 }
执行上面代码,将得到以下输出结果
1 2017-03-23T11:41:52+08:00 2 2012-11-01 22:08:41 +0000 +0000 3 11:41AM 4 Thu Mar 23 11:41:52 2017 5 2017-03-23T11:41:52.246508+08:00 6 0000-01-01 20:41:00 +0000 UTC 7 2017-03-23T11:41:52-00:00 8 parsing time "8:41PM" as "Mon Jan _2 15:04:05 2006": cannot parse "8:41PM" as "Mon"
2、字符串格式化
1 package main 2 3 import "fmt" 4 import "os" 5 6 type point struct { 7 x, y int 8 } 9 10 func main() { 11 p := point{1, 2} 12 fmt.Printf("%v\n", p) 13 14 fmt.Printf("%+v\n", p) 15 16 fmt.Printf("%#v\n", p) 17 18 fmt.Printf("%T\n", p) 19 20 fmt.Printf("%t\n", true) 21 22 fmt.Printf("%d\n", 123) 23 24 fmt.Printf("%b\n", 14) 25 26 fmt.Printf("%c\n", 33) 27 28 fmt.Printf("%x\n", 456) 29 30 fmt.Printf("%f\n", 78.9) 31 32 fmt.Printf("%e\n", 123400000.0) 33 fmt.Printf("%E\n", 123400000.0) 34 35 fmt.Printf("%s\n", "\"string\"") 36 37 fmt.Printf("%q\n", "\"string\"") 38 39 fmt.Printf("%x\n", "hex this") 40 41 fmt.Printf("%p\n", &p) 42 43 fmt.Printf("|%6d|%6d|\n", 12, 345) 44 45 fmt.Printf("|%6.2f|%6.2f|\n", 1.2, 3.45) 46 47 fmt.Printf("|%-6.2f|%-6.2f|\n", 1.2, 3.45) 48 49 fmt.Printf("|%6s|%6s|\n", "foo", "b") 50 51 fmt.Printf("|%-6s|%-6s|\n", "foo", "b") 52 53 s := fmt.Sprintf("a %s", "string") 54 fmt.Println(s) 55 56 fmt.Fprintf(os.Stderr, "an %s\n", "error") 57 }
1 {1 2} 2 {x:1 y:2} 3 main.point{x:1, y:2} 4 main.point 5 true 6 123 7 1110 8 ! 9 1c8 10 78.900000 11 1.234000e+08 12 1.234000E+08 13 "string" 14 "\"string\"" 15 6865782074686973 16 0xc042004280 17 | 12| 345| 18 | 1.20| 3.45| 19 |1.20 |3.45 | 20 | foo| b| 21 |foo |b | 22 a string 23 an error
3、正则表达式
1 package main 2 3 import "bytes" 4 import "fmt" 5 import "regexp" 6 7 func main() { 8 9 // This tests whether a pattern matches a string. 10 match, _ := regexp.MatchString("p([a-z]+)ch", "peach") 11 fmt.Println(match) 12 13 // Above we used a string pattern directly, but for 14 // other regexp tasks you'll need to `Compile` an 15 // optimized `Regexp` struct. 16 r, _ := regexp.Compile("p([a-z]+)ch") 17 18 // Many methods are available on these structs. Here's 19 // a match test like we saw earlier. 20 fmt.Println(r.MatchString("peach")) 21 22 // This finds the match for the regexp. 23 fmt.Println(r.FindString("peach punch")) 24 25 // This also finds the first match but returns the 26 // start and end indexes for the match instead of the 27 // matching text. 28 fmt.Println(r.FindStringIndex("peach punch")) 29 30 // The `Submatch` variants include information about 31 // both the whole-pattern matches and the submatches 32 // within those matches. For example this will return 33 // information for both `p([a-z]+)ch` and `([a-z]+)`. 34 fmt.Println(r.FindStringSubmatch("peach punch")) 35 36 // Similarly this will return information about the 37 // indexes of matches and submatches. 38 fmt.Println(r.FindStringSubmatchIndex("peach punch")) 39 40 // The `All` variants of these functions apply to all 41 // matches in the input, not just the first. For 42 // example to find all matches for a regexp. 43 fmt.Println(r.FindAllString("peach punch pinch", -1)) 44 45 // These `All` variants are available for the other 46 // functions we saw above as well. 47 fmt.Println(r.FindAllStringSubmatchIndex( 48 "peach punch pinch", -1)) 49 50 // Providing a non-negative integer as the second 51 // argument to these functions will limit the number 52 // of matches. 53 fmt.Println(r.FindAllString("peach punch pinch", 2)) 54 55 // Our examples above had string arguments and used 56 // names like `MatchString`. We can also provide 57 // `[]byte` arguments and drop `String` from the 58 // function name. 59 fmt.Println(r.Match([]byte("peach"))) 60 61 // When creating constants with regular expressions 62 // you can use the `MustCompile` variation of 63 // `Compile`. A plain `Compile` won't work for 64 // constants because it has 2 return values. 65 r = regexp.MustCompile("p([a-z]+)ch") 66 fmt.Println(r) 67 68 // The `regexp` package can also be used to replace 69 // subsets of strings with other values. 70 fmt.Println(r.ReplaceAllString("a peach", "<fruit>")) 71 72 // The `Func` variant allows you to transform matched 73 // text with a given function. 74 in := []byte("a peach") 75 out := r.ReplaceAllFunc(in, bytes.ToUpper) 76 fmt.Println(string(out)) 77 }
执行上面代码,将得到以下输出结果
1 true 2 true 3 peach 4 [0 5] 5 [peach ea] 6 [0 5 1 3] 7 [peach punch pinch] 8 [[0 5 1 3] [6 11 7 9] [12 17 13 15]] 9 [peach punch] 10 true 11 p([a-z]+)ch 12 a <fruit> 13 a PEACH
4、Json
1 package main 2 3 import "encoding/json" 4 import "fmt" 5 import "os" 6 7 // We'll use these two structs to demonstrate encoding and 8 // decoding of custom types below. 9 type Response1 struct { 10 Page int 11 Fruits []string 12 } 13 type Response2 struct { 14 Page int `json:"page"` 15 Fruits []string `json:"fruits"` 16 } 17 18 func main() { 19 20 // First we'll look at encoding basic data types to 21 // JSON strings. Here are some examples for atomic 22 // values. 23 bolB, _ := json.Marshal(true) 24 fmt.Println(string(bolB)) 25 26 intB, _ := json.Marshal(1) 27 fmt.Println(string(intB)) 28 29 fltB, _ := json.Marshal(2.34) 30 fmt.Println(string(fltB)) 31 32 strB, _ := json.Marshal("gopher") 33 fmt.Println(string(strB)) 34 35 // And here are some for slices and maps, which encode 36 // to JSON arrays and objects as you'd expect. 37 slcD := []string{"apple", "peach", "pear"} 38 slcB, _ := json.Marshal(slcD) 39 fmt.Println(string(slcB)) 40 41 mapD := map[string]int{"apple": 5, "lettuce": 7} 42 mapB, _ := json.Marshal(mapD) 43 fmt.Println(string(mapB)) 44 45 // The JSON package can automatically encode your 46 // custom data types. It will only include exported 47 // fields in the encoded output and will by default 48 // use those names as the JSON keys. 49 res1D := &Response1{ 50 Page: 1, 51 Fruits: []string{"apple", "peach", "pear"}} 52 res1B, _ := json.Marshal(res1D) 53 fmt.Println(string(res1B)) 54 55 // You can use tags on struct field declarations 56 // to customize the encoded JSON key names. Check the 57 // definition of `Response2` above to see an example 58 // of such tags. 59 res2D := &Response2{ 60 Page: 1, 61 Fruits: []string{"apple", "peach", "pear"}} 62 res2B, _ := json.Marshal(res2D) 63 fmt.Println(string(res2B)) 64 65 // Now let's look at decoding JSON data into Go 66 // values. Here's an example for a generic data 67 // structure. 68 byt := []byte(`{"num":6.13,"strs":["a","b"]}`) 69 70 // We need to provide a variable where the JSON 71 // package can put the decoded data. This 72 // `map[string]interface{}` will hold a map of strings 73 // to arbitrary data types. 74 var dat map[string]interface{} 75 76 // Here's the actual decoding, and a check for 77 // associated errors. 78 if err := json.Unmarshal(byt, &dat); err != nil { 79 panic(err) 80 } 81 fmt.Println(dat) 82 83 // In order to use the values in the decoded map, 84 // we'll need to cast them to their appropriate type. 85 // For example here we cast the value in `num` to 86 // the expected `float64` type. 87 num := dat["num"].(float64) 88 fmt.Println(num) 89 90 // Accessing nested data requires a series of 91 // casts. 92 strs := dat["strs"].([]interface{}) 93 str1 := strs[0].(string) 94 fmt.Println(str1) 95 96 // We can also decode JSON into custom data types. 97 // This has the advantages of adding additional 98 // type-safety to our programs and eliminating the 99 // need for type assertions when accessing the decoded 100 // data. 101 str := `{"page": 1, "fruits": ["apple", "peach"]}` 102 res := Response2{} 103 json.Unmarshal([]byte(str), &res) 104 fmt.Println(res) 105 fmt.Println(res.Fruits[0]) 106 107 // In the examples above we always used bytes and 108 // strings as intermediates between the data and 109 // JSON representation on standard out. We can also 110 // stream JSON encodings directly to `os.Writer`s like 111 // `os.Stdout` or even HTTP response bodies. 112 enc := json.NewEncoder(os.Stdout) 113 d := map[string]int{"apple": 5, "lettuce": 7} 114 enc.Encode(d) 115 }
执行上面代码,将得到以下输出结果
1 true 2 1 3 2.34 4 "gopher" 5 ["apple","peach","pear"] 6 {"apple":5,"lettuce":7} 7 {"Page":1,"Fruits":["apple","peach","pear"]} 8 {"page":1,"fruits":["apple","peach","pear"]} 9 map[num:6.13 strs:[a b]] 10 6.13 11 a 12 {1 [apple peach]} 13 apple 14 {"apple":5,"lettuce":7}
5、数字解析
1 package main 2 3 // The built-in package `strconv` provides the number 4 // parsing. 5 import "strconv" 6 import "fmt" 7 8 func main() { 9 10 // With `ParseFloat`, this `64` tells how many bits of 11 // precision to parse. 12 f, _ := strconv.ParseFloat("1.234", 64) 13 fmt.Println(f) 14 15 // For `ParseInt`, the `0` means infer the base from 16 // the string. `64` requires that the result fit in 64 17 // bits. 18 i, _ := strconv.ParseInt("123", 0, 64) 19 fmt.Println(i) 20 21 // `ParseInt` will recognize hex-formatted numbers. 22 d, _ := strconv.ParseInt("0x1c8", 0, 64) 23 fmt.Println(d) 24 25 // A `ParseUint` is also available. 26 u, _ := strconv.ParseUint("789", 0, 64) 27 fmt.Println(u) 28 29 // `Atoi` is a convenience function for basic base-10 30 // `int` parsing. 31 k, _ := strconv.Atoi("135") 32 fmt.Println(k) 33 34 // Parse functions return an error on bad input. 35 _, e := strconv.Atoi("wat") 36 fmt.Println(e) 37 }
执行上面代码,将得到以下输出结果
1 1.234 2 123 3 456 4 789 5 135 6 strconv.ParseInt: parsing "wat": invalid syntax
6、Url解析
1 package main 2 3 import "fmt" 4 import "net" 5 import "net/url" 6 7 func main() { 8 9 s := "postgres://user:pass@host.com:5432/path?k=v#f" 10 11 u, err := url.Parse(s) 12 if err != nil { 13 panic(err) 14 } 15 16 fmt.Println(u.Scheme) 17 18 fmt.Println(u.User) 19 fmt.Println(u.User.Username()) 20 p, _ := u.User.Password() 21 fmt.Println(p) 22 23 fmt.Println(u.Host) 24 host, port, _ := net.SplitHostPort(u.Host) 25 fmt.Println(host) 26 fmt.Println(port) 27 28 fmt.Println(u.Path) 29 fmt.Println(u.Fragment) 30 31 fmt.Println(u.RawQuery) 32 m, _ := url.ParseQuery(u.RawQuery) 33 fmt.Println(m) 34 fmt.Println(m["k"][0]) 35 }
执行上面代码,将得到以下输出结果
1 postgres 2 user:pass 3 user 4 pass 5 host.com:5432 6 host.com 7 5432 8 /path 9 f 10 k=v 11 map[k:[v]] 12 v
7、SHA1哈希
package main // Go implements several hash functions in various // `crypto/*` packages. import "crypto/sha1" import "fmt" func main() { s := "sha1 this string"//原始字符串 h := sha1.New()//加密对象 h.Write([]byte(s))//将原始字符串转换成字节切片传给加密对象 bs := h.Sum(nil)//哈希结果追加和片段 可以不需要 fmt.Println(s)//打印原始字符串 fmt.Printf("%x\n", bs)//输出哈希结果 }
执行上面代码,将得到以下输出结果
1 sha1 this string 2 cf23df2207d99a74fbe169e3eba035e633b65d94
8、Base64编码
Go提供对base64
编码/解码的内置支持。导入带有b64
名称的encoding/base64
软件包,而不是默认的base64
。它会节省我们一些空间。编码器需要一个[]byte
,所以将字符串转换为该类型。
1 import b64 "encoding/base64" 2 import "fmt" 3 4 func main() { 5 data := "abc123!?$*&()'-=@~" 6 7 sEnc := b64.StdEncoding.EncodeToString([]byte(data)) 8 fmt.Println(sEnc) 9 10 11 sDec, _ := b64.StdEncoding.DecodeString(sEnc) 12 fmt.Println(string(sDec)) 13 fmt.Println() 14 15 uEnc := b64.URLEncoding.EncodeToString([]byte(data)) 16 fmt.Println(uEnc) 17 uDec, _ := b64.URLEncoding.DecodeString(uEnc) 18 fmt.Println(string(uDec)) 19 }
执行上面代码,将得到以下输出结果
1 YWJjMTIzIT8kKiYoKSctPUB+ 2 abc123!?$*&()'-=@~ 3 4 YWJjMTIzIT8kKiYoKSctPUB- 5 abc123!?$*&()'-=@~
9、文件读写
读取和写入文件是许多Go
程序所需的基本任务。
1、读取文件
1 package main 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 ) 10 //检查error状态 如果包含错误信息 则使用panic中断 11 func check(e error) { 12 if e != nil { 13 panic(e) 14 } 15 } 16 17 func main() { 18 19 dat, err := ioutil.ReadFile("/tmp/dat")//直接读取文件内容到内存 20 check(err) 21 fmt.Print(string(dat)) 22 23 //使用os.Open打开文件 以获取文件的更多操作 24 f, err := os.Open("/tmp/dat") 25 check(err) 26 27 b1 := make([]byte, 5) 28 n1, err := f.Read(b1)//读取5个字节 29 check(err) 30 fmt.Printf("%d bytes: %s\n", n1, string(b1)) 31 32 o2, err := f.Seek(6, 0)//定位到文件开头6个字符后 33 check(err) 34 b2 := make([]byte, 2) 35 n2, err := f.Read(b2)//读取2个字节 36 check(err) 37 fmt.Printf("%d bytes @ %d: %s\n", n2, o2, string(b2)) 38 39 o3, err := f.Seek(6, 0) 40 check(err) 41 b3 := make([]byte, 2) 42 n3, err := io.ReadAtLeast(f, b3, 2)//使用io对象读取 43 check(err) 44 fmt.Printf("%d bytes @ %d: %s\n", n3, o3, string(b3)) 45 46 _, err = f.Seek(0, 0)//定位到文件开始位置 47 check(err) 48 49 r4 := bufio.NewReader(f)//bufio先读取到缓存 50 b4, err := r4.Peek(5)//然后从缓存中拿字节 比较高效 51 check(err) 52 fmt.Printf("5 bytes: %s\n", string(b4)) 53 54 f.Close() 55 }
执行上面代码,将得到以下输出结果
1 abcdfawef!@ 2 cawfe 3 awefawef 4 5 awefaf 6 5 bytes: abcdf 7 2 bytes @ 6: we 8 2 bytes @ 6: we 9 5 bytes: abcdf
2、文件写入
1 package main 2 3 import ( 4 "bufio" 5 "fmt" 6 "io/ioutil" 7 "os" 8 ) 9 10 func check(e error) { 11 if e != nil { 12 panic(e) 13 } 14 } 15 16 func main() { 17 d1 := []byte("hello\ngo\n") 18 err := ioutil.WriteFile("dat1.txt", d1, 0644) 19 check(err) 20 21 f, err := os.Create("dat2.txt") 22 check(err) 23 24 defer f.Close()//延迟关闭文件操作(f超出作用域) 25 26 d2 := []byte{115, 111, 109, 101, 10} 27 n2, err := f.Write(d2) 28 check(err) 29 fmt.Printf("wrote %d bytes\n", n2) 30 31 n3, err := f.WriteString("writes\n") 32 fmt.Printf("wrote %d bytes\n", n3) 33 34 f.Sync() 35 36 w := bufio.NewWriter(f) 37 n4, err := w.WriteString("buffered\n") 38 fmt.Printf("wrote %d bytes\n", n4) 39 40 w.Flush() 41 }
10、行过滤器
1 package main 2 3 import ( 4 "bufio"//读写 5 "fmt"//格式化输出 6 "os"//操作系统 7 "strings"//字符串 8 ) 9 10 func main() { 11 scanner := bufio.NewScanner(os.Stdin)//扫描标准输入 12 13 for scanner.Scan() { 14 ucl := strings.ToUpper(scanner.Text())//标 15 fmt.Println(ucl) 16 } 17 18 if err := scanner.Err(); err != nil {//发送错误 退出 19 fmt.Fprintln(os.Stderr, "error:", err) 20 os.Exit(1) 21 } 22 }
11、环境变量
通过os包获取和设置环境变量
1 package main 2 3 import "os" 4 import "strings" 5 import "fmt" 6 7 func main() { 8 9 // To set a key/value pair, use `os.Setenv`. To get a 10 // value for a key, use `os.Getenv`. This will return 11 // an empty string if the key isn't present in the 12 // environment. 13 os.Setenv("FOO", "1") 14 fmt.Println("FOO:", os.Getenv("FOO")) 15 fmt.Println("BAR:", os.Getenv("BAR")) 16 17 // Use `os.Environ` to list all key/value pairs in the 18 // environment. This returns a slice of strings in the 19 // form `KEY=value`. You can `strings.Split` them to 20 // get the key and value. Here we print all the keys. 21 fmt.Println() 22 for _, e := range os.Environ() { 23 pair := strings.Split(e, "=") 24 fmt.Println(pair[0]) 25 } 26 }
12、信号
信号通知通过在通道上发送os.Signal
值来工作。
1 package main 2 3 import "fmt" 4 import "os" 5 import "os/signal" 6 import "syscall" 7 8 func main() { 9 10 sigs := make(chan os.Signal, 1)//信号通道 11 done := make(chan bool, 1) 12 13 signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) 14 15 go func() { 16 sig := <-sigs//等待信号 17 fmt.Println() 18 fmt.Println(sig) 19 done <- true//发送给done通道 20 }() 21 22 fmt.Println("awaiting signal") 23 <-done//收到匿名函数发送的true值后 退出程序 24 fmt.Println("exiting") 25 }
执行上面代码,将得到以下输出结果
1 awaiting signal 2 [Ctl+C] 3 interrupt 4 exiting