Go 1.8的几个新特性

2017-02-17 阅读: Go

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

参考

标题:Go 1.8的几个新特性
本文链接:https://blog.frognew.com/2017/02/go-1.8-features.html
转载请注明出处。

目录