Help us understand the problem. What is going on with this article?

go1.7 の気になるところを試した

More than 3 years have passed since last update.

go1.7のbeta1がでたので、軽く個人的に気になるところを触ったメモ
以下、環境はOSXで、公式で配布されている go1.7beta1.darwin-amd64.tar.gz を使っています

目玉としては、生成されるバイナリの高速化や、GCの改善などがありますが、日常業務でそんなにGoのパフォーマンスに不満をもつ機会もないので、それ以外で気になったものを中心に試しました。

リリース予定は、順調にいけば8月です。

関連リンク

ダウンロード
https://golang.org/dl/#go1.7beta1

リリースノート
https://tip.golang.org/doc/go1.7

ビルドスピード

比較に使ったのは、仕事で使っているコードベースのビルド
generateされたコードも含めて、13万行ほどです。

go1.6

> /usr/bin/time -p go build cmd/tuner_server/main.go
real        18.80
user        30.14
sys          2.76

go1.7 beta-1

> /usr/bin/time -lp go build cmd/tuner_server/main.go
real        17.39
user        39.76
sys          4.32

ちょっと遅くなった... コードベースが大きいので、ほぼIOのスピードな感じはする。

ちなみに、バイナリサイズは、

version time
go1.6.1 35M
go1.7 beta-1 27M

かなりスリムになりました!

context パッケージ

今まで、 golang.org/x/net/context 配下 にあった、 context パッケージが、go 本体ライブラリに統合された。
context パッケージの役割については、Goの並行パターン:コンテキスト (Go Concurrency Pattern: Context) などを参照。

それと同時に、 *http.RequestContext() context.Context メソッドと、 WithContext(context.Context) *http.Request メソッドが追加された。

今まで、いろいろなフレームワークが、主にミドルウェアから各ハンドラへの情報の引き渡しのために、独自のコンテキスト構造を持っていたが、1.7からはデフォルトのcontextを使うことで、ミドルウェアの型を、func(http.Handler) http.Handler に統一できてすっきりする。
今までは各フレームワーク感で型が統一されてないので、ミドルウェアの再利用性が低かったけど、 nodeの connect みたいなミドルウェアを集めたパッケージがいろいろと出てくるんじゃないかと思われし、各種フレームワークも context パッケージを使うように落ち着くんじゃないかなぁと個人的には思っている。

context の使い方サンプル

package main

import (
    "context"
    "fmt"
    "net"
    "net/http"
    "net/http/httptest"
)

var middlewareKey = "m"

func middleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()
        ctx = context.WithValue(ctx, middlewareKey, "string set in middleware")
        cr := r.WithContext(ctx)
        next.ServeHTTP(w, cr)
    })
}

func main() {
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()

        // デフォルトで context に紐付いている値たち

        // サーバーがlistenしてるアドレス
        _ = ctx.Value(http.LocalAddrContextKey).(net.Addr)
        // サーバー自体のオブジェクト
        _ = ctx.Value(http.ServerContextKey).(*http.Server)

        // ミドルウェアでリクエストに関連付けた値を取得する
        fmt.Println(ctx.Value(middlewareKey))
    })

    ts := httptest.NewServer(middleware(handler))
    defer ts.Close()

    http.Get(ts.URL)
}

テストの subset 機能

テストの、サブセット機能がサポートされた

package main

import "testing"

func TestMain(t *testing.T) {
    t.Parallel()

    t.Run("Sub1", func(t *testing.T) {
        t.Run("SubA", func(t *testing.T) {
        })
        t.Run("SubB", func(t *testing.T) {
        })
    })
    t.Run("Sub2", func(t *testing.T) {
        t.Run("SubA", func(t *testing.T) {
        })
        t.Run("SubB", func(t *testing.T) {
        })
    })
}

のようなテストを書き go test -v すると

=== RUN   TestMain
=== RUN   TestMain/Sub1
=== RUN   TestMain/Sub1/SubA
=== RUN   TestMain/Sub1/SubB
=== RUN   TestMain/Sub2
=== RUN   TestMain/Sub2/SubA
=== RUN   TestMain/Sub2/SubB
--- PASS: TestMain (0.00s)
    --- PASS: TestMain/Sub1 (0.00s)
        --- PASS: TestMain/Sub1/SubA (0.00s)
        --- PASS: TestMain/Sub1/SubB (0.00s)
    --- PASS: TestMain/Sub2 (0.00s)
        --- PASS: TestMain/Sub2/SubA (0.00s)
        --- PASS: TestMain/Sub2/SubB (0.00s)
PASS
ok      /path-to-package  0.008s

のようになる

-run オプションの指定

Goのテストは、-run オプションで正規表現にマッチしたもののみ実行できるが、このオプションをsubsetになっているテストにも適用できる。
指定する場合は、階層毎に、/ で区切り、正規表現で指定する。
上の例だと以下の様な感じ。

2階層目が Sub2 のものだけ実行

> go test -v -run .*/Sub2
=== RUN   TestMain
=== RUN   TestMain/Sub2
=== RUN   TestMain/Sub2/SubA
=== RUN   TestMain/Sub2/SubB
--- PASS: TestMain (0.00s)
    --- PASS: TestMain/Sub2 (0.00s)
        --- PASS: TestMain/Sub2/SubA (0.00s)
        --- PASS: TestMain/Sub2/SubB (0.00s)
PASS
ok      /path-to-package   0.008s

3階層目が SubB のものだけ実行

> go test -v -run .*/.*/SubB
=== RUN   TestMain
=== RUN   TestMain/Sub1
=== RUN   TestMain/Sub1/SubB
=== RUN   TestMain/Sub2
=== RUN   TestMain/Sub2/SubB
--- PASS: TestMain (0.00s)
    --- PASS: TestMain/Sub1 (0.00s)
        --- PASS: TestMain/Sub1/SubB (0.00s)
    --- PASS: TestMain/Sub2 (0.00s)
        --- PASS: TestMain/Sub2/SubB (0.00s)
PASS
ok      /path-to-package   0.007s

テストの構造化と、ピンポイントで走らせてサイクルを回すのがやりやすくなりそう。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away