Go
golang

go1.10beta1の標準パッケの大きな変更点を確認しておく。

More than 1 year has passed since last update.


プログラミング言語のベータ版を触っておくという事。

プログラミング言語のβ版を触っておくと言う事は、今まで非常にハードルが高かったかもしれません。

親しみのある開発環境を一新し、パスを通し、あるいは最初から作らなければなりません。

しかし、世はまさに大コンテナ時代、dockerを使う事により手軽に試せる時代なのです。

β版を触れるという事はロマンであり、

バグを発見したらプログラミング言語のコントリビュータとして友達や同僚に自慢できます。

という訳でやっていきましょう。1


Getting Start 😆

https://godoc.org/golang.org/x/build/version/go1.10beta1

爆速で環境構築する。

$ docker run -it golang

$ go get golang.org/x/build/version/go1.10beta1
$ go1.10beta1 download
$ /root/sdk/go1.10beta1/bin/go version
go version go1.10beta1 linux/amd64

ダウンロードは時間かかります。

もっとなんども作って壊したいという人もいるでしょうから、

dockerイメージを事前に用意しました👍

$ docker pull nnao45/go1.10beta1

$ docker run -it nnao45/go1.10beta1
$ /root/sdk/go1.10beta1/bin/go version
go version go1.10beta1 linux/amd64

/root/sdk/go1.10beta1/bin/goのパスにベータ版が置いてあるので、フルパスで打ってください。比較用にわざとPATHの通っているversion1.9.2のgoも残してあるのですぐに比較ができます。

さぁ、dockerイメージかベータ版のインストール中のその隙にリリースノートを読むぞ〜〜〜!!

https://beta.golang.org/doc/go1.10

alt

こ、ここはあいわかったぞ!


All of the changes to the standard library are minor. The changes in bytes and net/url are the most likely to require updating of existing programs.

標準ライブラリへのすべての変更は軽微です。bytesnet/urlの変更は、既存のプログラムの更新を必要とする可能性が最も高いです。


https://beta.golang.org/doc/go1.10#library

ツー訳でこの2つの標準パッケの新しいメソッドを見ていけばいいんじゃ無いかな!!

お、そんなこと言ってたら終わりましたかね。

とにかくやって見ます。


bytes


bytes

The Fields, FieldsFunc, Split, and SplitAfter each already returned slices pointing into the same underlying array as its input. Go 1.10 changes each of the returned subslices to have capacity equal to its length, so that appending to a subslice will not overwrite adjacent data in the original input.

Fields、FieldsFunc、Split、SplitAfterは、入力と同じ基本配列を指し示す既に返されたスライスです。 Go 1.10は、返された各サブスライスの長さが容量に等しくなるように変更するので、サブスライスへの追加は元の入力内の隣接データを上書きしません。


https://beta.golang.org/doc/go1.10#bytes

日本語でおk。


bytes.Fields

これに関してはFieldsモジュールだけ見りゃOK。

func Fields(s []byte) [][]byte


Fields interprets s as a sequence of UTF-8-encoded code points. It splits the slice s around each instance of one or more consecutive white space characters, as defined by unicode.IsSpace, returning a slice of subslices of s or an empty slice if s contains only white space.

Fieldsは、sをUTF-8でコード化されたコードポイントのシーケンスとして解釈します。これは、unicode.IsSpaceで定義されているように、1つ以上の連続する空白文字の各インスタンスの周りにスライスを分割します.sのサブスライスのスライスまたは空のスライスだけが空白のスライスを返します。


https://beta.golang.org/pkg/bytes/#Fields

まぁ動きはわかったわ。


go1.9.2の場合

package main

import (
"fmt"
"bytes"
)

func main() {
b := []byte(" foo bar baz ")
fmt.Printf("%q\n", bytes.Fields(b)) //=> ["foo" "bar" "baz"]
fmt.Println(len(bytes.Fields(b))) //=> 3
fmt.Println(cap(bytes.Fields(b))) //=> 3
for i, sub := range bytes.Fields(b) {
fmt.Printf("index:%d %q\n", i, sub)
fmt.Println(len(sub))
fmt.Println(cap(sub))
/*
index:0 "foo"
3
30
index:1 "bar"
3
26
index:2 "baz"
3
21
*/

}
}

https://play.golang.org/p/b_n5Rv1QvX

とあるバイト列が1つ以上のスペースを含む時に、そのスペースを区切り文字として、配列を組み直して返すような関数のようです(使ったことない笑)

ん・・・?確かに。"foo"や"bar"が容量が確かに大きい気がします。utf-8の文字列の[]byteであれば3byteで良さそうなもんです。


go1.10beta1の場合

package main

import (
"fmt"
"bytes"
)

func main() {
b := []byte(" foo bar baz ")
fmt.Printf("%q\n", bytes.Fields(b)) //=> ["foo" "bar" "baz"]
fmt.Println(len(bytes.Fields(b))) //=> 3
fmt.Println(cap(bytes.Fields(b))) //=> 3
for i, sub := range bytes.Fields(b) {
fmt.Printf("index:%d %q\n", i, sub)
fmt.Println(len(sub))
fmt.Println(cap(sub))
/*
index:0 "foo"
3
3
index:1 "bar"
3
3
index:2 "baz"
3
3
*/

}
}

おお、綺麗に3byteと言う最低限の容量でおさまっております!!


net/url


net/url

ResolveReference now preseves multiple leading slashes in the target URL. Previously it rewrote multiple leading slashes to a single slash, which resulted in the http.Client following certain redirects incorrectly.

ResolveReferenceは、ターゲットURLの複数の先頭のスラッシュを保持します。これまでは複数の先頭のスラッシュを1つのスラッシュに書き直していたため、特定のリダイレクトに続いてhttp.Clientが誤っていました。


https://beta.golang.org/doc/go1.10#net/url

え?😱


For example, this code's output has changed:


base, _ := url.Parse("http://host//path//to/page1")

target, _ := url.Parse("page2")
fmt.Println(base.ResolveReference(target))


ResolveReference

func (u *URL) ResolveReference(ref *URL) *URL


ResolveReference resolves a URI reference to an absolute URI from an absolute base URI, per RFC 3986 Section 5.2. The URI reference may be relative or absolute. ResolveReference always returns a new URL instance, even if the returned URL is identical to either the base or reference. If ref is an absolute URL, then ResolveReference ignores base and returns a copy of ref.

ResolveReferenceはRFC 3986セクション5.2で絶対URIへのURI参照を絶対基底URIから解決します。 URI参照は、相対的であっても絶対的であってもよい。 ResolveReferenceは、返されたURLがベースまたは参照のいずれかと同一であっても、常に新しいURLインスタンスを返します。 refが絶対URLの場合、ResolveReferenceはbaseを無視してrefのコピーを返します。


https://beta.golang.org/pkg/net/url/#URL.ResolveReference

日本語でおk


go1.9.2の場合

package main

import (
"fmt"
"net/url"
)

func main() {
base, _ := url.Parse("http://host//path//to/page1")
target, _ := url.Parse("page2")
fmt.Println(base.ResolveReference(target)) //=> http://host/path//to/page2
}

ポイントは、http://host//path//to/page1のダブルスラッシュの部分です。

出力では1個目のダブルスラッシュが消えてしまっています。


go1.10beta1の場合

package main

import (
"fmt"
"net/url"
)

func main() {
base, _ := url.Parse("http://host//path//to/page1")
target, _ := url.Parse("page2")
fmt.Println(base.ResolveReference(target)) //=> http://host//path//to/page2
}

しっかり直ってますね・・・パースミスだったのでしょうかね。

ドキュメントではこんなことが書いてあります。


Note the doubled slashes around path. In Go 1.9 and earlier, the resolved URL was http://host/path//to/page2: the doubled slash before path was incorrectly rewritten to a single slash, while the doubled slash after path was correctly preserved. Go 1.10 preserves both doubled slashes, resolving to http://host//path//to/page2 as required by RFC 3986.

パスの周りの倍のスラッシュに注意してください。 Go 1.9以前では、解決されたURLはhttp:// host / path // to / page2でした。パスの後に二重スラッシュが間違って1つのスラッシュに書き換えられる前に、二重スラッシュが正しく保存されました。 Go 1.10は、RFC 3986で要求されているように、http:// host // path / to / page2に解決された二重のスラッシュを保存します。

This change may break existing buggy programs that unintentionally construct a base URL with a leading doubled slash in the path and inadvertently depend on ResolveReference to correct that mistake. For example, this can happen if code adds a host prefix like http://host/ to a path like /my/api, resulting in a URL with a doubled slash: http://host//my/api.

この変更により、パスの先頭に2つのスラッシュを含むベースURLが誤って作成され、誤ってそのエラーを修正するためにResolveReferenceに依存する既存のバギープログラムが壊れる可能性があります。たとえば、コードがhttp:// host /のようなホストプレフィックスを/ my / apiのようなパスに追加すると、http:// host // my / apiのように二重スラッシュのURLが生成されます。


要はこのバグを直すためにパースしなおしてるプログラムが壊れるかもよってことか。

注意されたし。


感想

dockerは神。dockerで手軽にベータ版を試していきましょう。





  1. 当然ながら、マスターリリースでは今回のリリースノートの内容は変更されてしまう可能性、さらにリリースノート以外の内容が追加、削除される可能性はもちろんありますので、そこはお間違えのないよう。