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都被处理完。

参考