LoginSignup
22
5

More than 5 years have passed since last update.

Go 1.12 beta 1 の標準パッケージの中で気になったマイナーチェンジを Docker で試したので紹介する。

Last updated at Posted at 2018-12-22

Gopher道場 Advent Calendar 2018 の 22日目のエントリです。
昨日は hiokidaichi さんの Mac の Go で birth time を取得する でした!!

追記 2019/2/26

go1.12がリリースされました!!

はじめに

きたる 2019/2 に Go 1.12 がリリースされる予定です。一方で 2018/12 現在、Go 1.12 の beta版の機能を試すことができます。Docker環境立てて、Go 1.12 の中で気になった機能を試して見たので紹介します。せっかくなので Go 1.12 の Docker環境の立て方も紹介します。ここで紹介する機能は現在WIPなので注意!!

Go 1.12 beta 1 の Docker 環境を準備

もっと最適化はできると思いますが、下の Dockerfile を準備したら終わり。

FROM centos:centos7

WORKDIR /home/go
ENV PATH $PATH:/usr/local/bin/go/bin
RUN curl -O https://storage.googleapis.com/golang/go1.12beta1.linux-amd64.tar.gz \
    && tar -C /usr/local/bin -xzf go1.12beta1.linux-amd64.tar.gz \
    && rm go1.12beta1.linux-amd64.tar.gz \
    && yum -y update && yum clean all \
    && yum install -y vim && yum clean all

go1.12beta1.linux-amd64.tar.gz をダウンロード & 解凍して go にパスを通して エディターの vim を追加しています。これを走らせましょう。

$ docker build ./ -t go1.12
$ docker run -it --name go1.12 go1.12 /bin/bash

docker run でコンテナに入ったら確認です。

$ go version
go1.12beta1 linux/amd64

go1.12beta1 が入りました。

bytes.ReplaceAll

bytes パッケージの新しい関数。

func ReplaceAll(s, old, new []byte) []byte

bytes.ReplaceAllは、soldnew に置き換えたバイトスライスのコピーを返す。

package main // import "try-go112"

import (
    "fmt"
    "bytes"
)

func main(){
    // qux qux bar bar baz baz
    fmt.Printf("%s\n", bytes.ReplaceAll([]byte("foo foo bar bar baz baz"), []byte("foo"), []byte("qux")))
}

strings.ReplaceAll

先ほどの bytes.ReplaceAll の string バージョンも追加される。

func ReplaceAll(s, old, new string) string

使用例はこちら

package main // import "try-go112"

import (
        "fmt"
        "strings"
)

func main(){
        // moo moo moo
        fmt.Println(strings.ReplaceAll("oink oink oink", "oink", "moo"))
}

expvar.Delete

expvar パッケージは メトリクスを簡単に所得できる便利な標準パッケージ。expvar パッケージに関しては下記の記事が参考になりそう。
https://qiita.com/methane/items/8f56f663d6da4dee9f64

そして、Go 1.12 からの新しい関数が追加。メトリクスのマップからキーを指定して削除できます。

func (v *Map) Delete(key string)

このパッケージは使ったことないのですが、そもそも今まで削除どうやってたんだろう。下が使用例。

package main // import "try-go112"

import (
    "expvar"
    "fmt"
)

func main() {
    Map := expvar.NewMap("myapp")

    Conns := new(expvar.Int)
    MessageRecv := new(expvar.Int)
    MessageSent := new(expvar.Int)

    Map.Set("conns", Conns)
    Map.Set("msg_recv", MessageRecv)
    Map.Set("msg_sent", MessageSent)

    Map.Delete("msg_recv")
    str := Map.String()

    // {"conns": 0, "msg_sent": 0}
    fmt.Println(str)
}

fmt

map を print する際に key でソートされて出力されるようになる。

package main // import "try-go112"

import "fmt"

func main() {
    m := map[interface{}]interface{}{
        "go":  "golang",
        "rb":  "ruby",
        "js":  "javascript",
    }
    // map[go:golang js:javascript rb:ruby]
    fmt.Println(m)
}

ソートのルールは https://tip.golang.org/doc/go1.12#fmt で確認できる。

io.StringWritter

新しいインターフェースが公開される。今まで io.stringWriter インターフェースがありましたが(実装は全く同じ)、このインターフェースは外部にエクスポートされていませんでした。しかし、Go 1.12 から 外から使える io.WriteStringer インターフェースが追加されています。

type StringWriter interface {
    WriteString(s string) (n int, err error)
}
package main // import "try-go112"

import (
        "fmt"
        "io"
)


type User struct {
        Name string
}

func (u *User) WriteString(s string) (n int, err error) {
        // 実装は適当
        fmt.Printf("to %v, %v \n", u.Name, s)
        return 1, nil
}

func main() {
        u := &User{
                Name: "po3rin",
        }
        checkStringWriter(u)
}

func checkStringWriter(v interface{}) {
        // io.StringWriterの実装を確認。
        if _, ok := v.(io.StringWriter); ok {
                fmt.Println("impliments StringWriter")
        }
}

os.ProcessState.ExitCode

os.ProcessState から 新しいメソッドが生える。

func (p *ProcessState) ExitCode() int

終了したプロセスの終了コードを返してくれる。プロセスが終了していないかシグナルによって終了した場合は-1を返します。

package main // import "try-go112"

import (
        "fmt"
        "os"
        "os/exec"
)

func main() {
        if len(os.Args) == 1 {
                return
        }
        cmd := exec.Command(os.Args[1], os.Args[2:]...)
        cmd.Run()
        state := cmd.ProcessState
        fmt.Println(state.ExitCode())
}

reflect.MapIter

新しく reflect.MapIter が実装される。

type MapIter struct {
    // contains filtered or unexported fields
}

MapIter は下記のメソッドで初期化する。

func (v Value) MapRange() *MapIter

MapRangeは、reflect.Valueに新しく実装されるメソッドで Map のイテレータ MapIter を返します。vの種類が Map でない場合はパニックになります。

reflect.MapIter には3つのメソッドが生えている。

func (it *MapIter) Next() bool

マップのイテレータを進めていきます。イテレータが終わるとfalseを返します。

func (it *MapIter) Key() Value

イテレータの現在のマップのエントリのキーを返します。

func (it *MapIter) Value() Value

イテレータの現在のマップのエントリの値を返します。

使用例は下記。マップに対する反復処理ができます。

package main // import "try-go112"

import (
    "fmt"
    "reflect"
)

func main() {
    m := map[string]interface{}{
        "name":"po3rin",
        "age": 27,
        "live": "tokyo",
    }
    iter := reflect.ValueOf(m).MapRange()
    for iter.Next() {
        k := iter.Key()
        v := iter.Value()

        fmt.Printf("key: %v, val: %v \n", k, v)
    }
}

「for文で回すのと何が違うの?」となるが、*MapIter.Value()*MapIter.Key()reflect.Valueインターフェースとして返してくれるので、そのまま reflect.Value に対しての処理ができる。

strings.Builder.Cap

この前 https://qiita.com/po3rin/items/2e406645e0b64e0339d3 で紹介したstrings.Builder ですが、そこに新しくメソッドが追加されます。

func (b *Builder) Cap() int

単に今の Builder のバイトスライスの容量を返します。使うと下のようになります。

package main // import "try-go112"

import (
        "fmt"
        "strings"
)

func main(){
        var b strings.Builder
        b.Grow(10)

        // 10
        fmt.Println(b.Cap())
}

その他、気になった変更点

Binary-only packages のサポートが Go 1.12 で最後

Binary-only packages
Go 1.12 is the last release that will support binary-only packages.

Binary-only packages のサポートが Go.1.12 で最後になるよう。Binary-only packages に関しては僕も過去に記事にしていた。

Go言語 で ソースコードを含めない「Binary-Only Package」を作ってみる!

-benchtime flag

テストのくり返し回数の設定をサポートするようになります。たとえば、-benchtime=100x はベンチマークを100回実行します。

go test -bench . -benchtime=100x

crypto/tls が TLS 1.3 をサポート

crypto/tlsパッケージに RFC8446 で明示されている TLS 1.3 のサポートが追加されます。Configに明示的にMaxVersionを設定していなければ、利用可能な場合、自動的に TLS 1.3 を使用するようになる。

まとめ

楽しみ Go1.12 !! もし間違った情報があったら教えてください。

この他にもたくさんの変更が入る予定なので是非リリースノートを確認してみてください。
Go 1.12 Release Notes

22
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
5