Go 1.8的几个新特性
📅 2017-02-17 | 🖱️
🔖 go
Go1.8发布了,这里先简单学习一下Go1.8的几个新特性。
新的切片排序Api #
在以前要对切片排序要实现sort.Interface接口:
1package main
2
3import (
4 "fmt"
5 "sort"
6)
7
8type Person struct {
9 Name string
10 Age int
11}
12
13func (p Person) String() string {
14 return fmt.Sprintf("%s: %d", p.Name, p.Age)
15}
16
17// ByAge implements sort.Interface for []Person based on
18// the Age field.
19type ByAge []Person
20
21func (a ByAge) Len() int { return len(a) }
22func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
23func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
24
25func main() {
26 people := []Person{
27 {"Bob", 31},
28 {"John", 42},
29 {"Michael", 17},
30 {"Jenny", 26},
31 }
32
33 fmt.Println(people)
34 sort.Sort(ByAge(people))
35 fmt.Println(people)
36
37}
现在只需这样做:
1package main
2
3import (
4 "fmt"
5 "sort"
6)
7
8type Person struct {
9 Name string
10 Age int
11}
12
13func (p Person) String() string {
14 return fmt.Sprintf("%s: %d", p.Name, p.Age)
15}
16
17func main() {
18 people := []Person{
19 {"Bob", 31},
20 {"John", 42},
21 {"Michael", 17},
22 {"Jenny", 26},
23 }
24
25 fmt.Println(people)
26 sort.Slice(people, func(i, j int) bool {
27 return people[i].Age < people[j].Age
28 })
29 fmt.Println(people)
30}
plugin包实现动态插件功能 #
当前这个plugin功能只在linux系统上好用。
一个plugin指的是Go的main包以go build -buildmode=plugin
构建,以暴露包内的函数和变量。
hello_plugin.go:
1package main
2
3import "fmt"
4
5var V int
6
7func F() {
8 fmt.Printf("Hello, number %d\n", V)
9}
编译插件得到hello_plugin.so,需要GCC。
1go build -buildmode=plugin hello_plugin.go
2ls
3hello_plugin.go hello_plugin.so
使用插件:
1package main
2
3import (
4 "plugin"
5)
6
7func main() {
8 p, err := plugin.Open("hello_plugin.so")
9 if err != nil {
10 panic(err)
11 }
12 v, err := p.Lookup("V")
13 if err != nil {
14 panic(err)
15 }
16 f, err := p.Lookup("F")
17 if err != nil {
18 panic(err)
19 }
20 *v.(*int) = 7
21 f.(func())() // prints "Hello, number 7"
22}
Http Server Graceful Shutdown #
1package main
2
3import (
4 "context"
5 "io"
6 "log"
7 "net/http"
8 "os"
9 "os/signal"
10 "time"
11)
12
13func main() {
14 stopChan := make(chan os.Signal)
15 // 订阅SIGINT信号
16 signal.Notify(stopChan, os.Interrupt)
17
18 mux := http.NewServeMux()
19 mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
20 time.Sleep(time.Second * 5)
21 io.WriteString(w, "Hello")
22 })
23
24 server := &http.Server{Addr: ":8080", Handler: mux}
25
26 go func() {
27 if err := server.ListenAndServe(); err != nil {
28 log.Println("server.ListenAndServe():", err)
29 }
30 }()
31
32 // 等待SIGINT信号
33 <-stopChan
34
35 log.Println("Shuting down ...")
36
37 ctx, _ := context.WithTimeout(context.Background(), time.Second*6)
38 server.Shutdown(ctx)
39
40 log.Println("The Server is gracefully stopped!")
41}
收到SIGINT信号,Http Server会马上停止接受新的连接,srv.ListenAndServe()会返回http: Server closed
错误,代码执行到srv.Shutdown后会一直阻塞,直到之前所有未完成的request都被处理完。