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