A few notable changes in Go 1.9

Source: Internet
Author: User
Tags benchmark gopher cloudflare tiobe index
This is a creation in Article, where the information may have evolved or changed.

The go language was elected Tiobe Index's annual programming language in 2016.

In a blink of an eye 6 months later, go in the Tiobe index list continues to rise strongly, in the latest released Tiboe index July, go advance Top10:

In less than one months, the Go 1.9 version is officially released (planned for August), the latest version of Go 1.9 is GO1.9BETA2, the experimental environment is based on this version, it is estimated that the final go 1.9 version will not be much different. At this year's Gopherchina conference, I mentioned: Go has evolved to 1.9, then go 1.10 or go 2? Now the answer has been announced: Go 1.10. It is estimated that go core team thinks that go 1 still has a lot to be improved and optimized, or that the Go2 time is still not there. Go team's tech lead Russ Cox will make a keynote speech titled "The Future of Go" at this year's Gophercon conference and look forward to getting some information about the go in the mouth of Russ.

To get to the point, let's take a look at what the go 1.9 is worth our attention to, although I personally feel that the Go1.9 of change is not very ^0^.

First, Type alias

Go 1.9 is still part of the GO1 system and therefore continues to comply with GO1 compatibility commitments. This is almost always mentioned in my "several changes to watch" series.

However, go 1.9 adds a "controversial" syntax to the language syntax: Type Alias. The proposal about type Alias was originally presented by Robert Griesemer, one of the father of the go language, and is scheduled to be added to the go language in go 1.8. However, because the type alias of Go 1.8 was too hasty to test enough to find a problem that could not be solved shortly when it was released near go 1.8, go team decided to rollback the implementation of type alias from Go 1.8.

At the start of Go 1.9 dev cycle, type alias is re-incorporated. This time Russ Cox personally wrote the article "Codebase refactoring (with help from Go)" to pave the addition of type Alias, and to open the new discussion to the previous Go 1.8 general The alias syntax is further optimized, and the final 1.9 simply chooses the type alias, without the need to introduce the new operator (= =) as in the general alias in Go 1.8. In this way, combined with the interchangeable constant, function, variable, plus the type Alias,go finally implemented on the language level "gradual code repair (progressive code refactoring)" Initial support of the concept.

Note: Due to the addition of type alias, it is a good idea to upgrade your local editor/ide plug-ins (such as Vim-go, vscode-go) and various tools versions before doing the Go 1.9 related code experiment.

The official definition of type alias is simple:

An alias declaration binds a identifier to the given type.

How do we understand the difference between the new type alias and the traditional type definition?

type T1 T2  // 传统的type defintionvs.type T1 = T2 //新增的type alias

Hold on: The traditional type definition creates a "new type", and the type alias does not create a "new type". If we have a type called "Monkey King", then we can write the following interesting code:

type  超级赛亚人  孙悟空type  卡卡罗特 = 孙悟空

At this time, we have two types: Monkey King and super-race . We define a super-Isaiah human type as a blueprint for the Monkey King, and when we use the alias of Kaka , the actual use is the Monkey King type, because Kaka is the Monkey King, the Monkey King is Kaka Rochester.

Let's take a couple of small examples and compare them carefully:

1. Assign Value

Go emphasizes explicit type conversions, so a new type defined with a traditional type definition needs to be explicitly transformed to the right variable when its variable is assigned, or the compiler will give an error.

//github.com/bigwhite/experiments/go19-examples/typealias/typedefinitions-assignment.gopackage main// type definitionstype MyInt inttype MyInt1 MyIntfunc main() {    var i int = 5    var mi MyInt = 6    var mi1 MyInt1 = 7    mi = MyInt(i)  // ok    mi1 = MyInt1(i) // ok    mi1 = MyInt1(mi) // ok    mi = i   //Error: cannot use i (type int) as type MyInt in assignment    mi1 = i  //Error: cannot use i (type int) as type MyInt1 in assignment    mi1 = mi //Error: cannot use mi (type MyInt) as type MyInt1 in assignment}

The type alias does not create a new type, only the "alias" of the source type, which is consistent with the source type on the type information and therefore can be assigned directly:

//github.com/bigwhite/experiments/go19-examples/typealias/typealias-assignment.gopackage mainimport "fmt"// type aliastype MyInt = inttype MyInt1 = MyIntfunc main() {    var i int = 5    var mi MyInt = 6    var mi1 MyInt1 = 7    mi = i // ok    mi1 = i // ok    mi1 = mi // ok    fmt.Println(i, mi, mi1)}

2. Type method

New types in Go1 that are defined by type definition do not inherit the method set from the source type:

// github.com/bigwhite/experiments/go19-examples/typealias/typedefinition-method.gopackage main// type definitionstype MyInt inttype MyInt1 MyIntfunc (i *MyInt) Increase(a int) {    *i = *i + MyInt(a)}func main() {    var mi MyInt = 6    var mi1 MyInt1 = 7    mi.Increase(5)    mi1.Increase(5) // Error: mi1.Increase undefined (type MyInt1 has no field or method Increase)}

But the type alias obtained by the type alias has the method set of the source type (because this is a type), and the method defined by the alias type is also reflected in the source type:

// github.com/bigwhite/experiments/go19-examples/typealias/typealias-method1.gopackage maintype Foo struct{}type Bar = Foofunc (f *Foo) Method1() {}func (b *Bar) Method2() {}func main() {    var b Bar    b.Method1() // ok    var f Foo    f.Method2() // ok}

Also, for a non-local type of source type, we cannot add a new method to it through the type alias:

//github.com/bigwhite/experiments/go19-examples/typealias/typealias-method.gopackage maintype MyInt = intfunc (i *MyInt) Increase(a int) { // Error: cannot define new methods on non-local type int    *i = *i + MyInt(a)}func main() {    var mi MyInt = 6    mi.Increase(5)}

3. Type embedding

With the result of the type method above, we can also directly know the difference between type definition and type alias in embedding.

// github.com/bigwhite/experiments/go19-examples/typealias/typedefinition-embedding.gopackage maintype Foo struct{}type Bar Footype SuperFoo struct {    Bar}func (f *Foo) Method1() {}func main() {    var s SuperFoo    s.Method1() //Error: s.Method1 undefined (type SuperFoo has no field or method Method1)}

Vs.

// github.com/bigwhite/experiments/go19-examples/typealias/typealias-embedding.gopackage maintype Foo struct{}type Bar = Footype SuperFoo struct {    Bar}func (f *Foo) Method1() {}func main() {    var s SuperFoo    s.Method1() // ok}

The alias bar obtained by the type alias is embedded in the other type, which still carries the method set of the source Type Foo.

4. Interface type

The definition of the identical of an interface type determines whether the following assignment is true regardless of the method used:

// github.com/bigwhite/experiments/go19-examples/typealias/typealias-interface.gopackage maintype MyInterface interface{    Foo()}type MyInterface1 MyInterfacetype MyInterface2 = MyInterfacetype MyInt intfunc (i *MyInt)Foo() {}func main() {    var i MyInterface = new(MyInt)    var i1 MyInterface1 = i // ok    var i2 MyInterface2 = i1 // ok    print(i, i1, i2)}

5. Exported Type Alias

As mentioned earlier, the type alias is almost the same as the source type, and the type alias has an attribute: You can export the unexported type in the package by declaring exported type alias:

//github.com/bigwhite/experiments/go19-examples/typealias/typealias-export.gopackage mainimport (    "fmt"    "github.com/bigwhite/experiments/go19-examples/typealias/mylib")func main() {    f := &mylib.Foo{5, "Hello"}    f.String()            // ok    fmt.Println(f.A, f.B) // ok    // Error:  f.anotherMethod undefined (cannot refer to unexported field    // or method mylib.(*foo).anotherMethod)    f.anotherMethod()}

The code for the Mylib package is as follows:

package mylibimport "fmt"type foo struct {    A int    B string}type Foo = foofunc (f *foo) String() {    fmt.Println(f.A, f.B)}func (f *foo) anotherMethod() {}

Second, Parallel complication (parallel compilation)

The build performance of the go 1.8 version of GC compiler, although it has been boosted by a big cut when compared to go 1.5, still has room for improvement, although go team is no longer as concerned about improving compiler performance as go 1.6.

In Go 1.9, the parallel compilation at the original support package level is implemented concurrently with the package function level to make fuller use of multicore resources. By default, parallel compilation is enabled and can be closed by go19concurrentcompilation=0.

On a 4-core VM of Aliyun ECS, we compare the differences between parallel compilation and shutdown parallelism:

# time GO19CONCURRENTCOMPILATION=0 go1.9beta2 build -a stdreal    0m16.762suser    0m28.856ssys    0m4.960s# time go1.9beta2 build -a stdreal    0m13.335suser    0m29.272ssys    0m4.812s

You can see that when parallel compilation is turned on, the GC's compilation performance is increased by 20% (realtime).

The comparison results on my Mac two-core PC are as follows:

$time GO19CONCURRENTCOMPILATION=0 go build -a stdreal    0m16.631suser    0m36.401ssys    0m8.607s$time  go build -a stdreal    0m14.445suser    0m36.366ssys    0m7.601s

increase by about 13%.

Third, "./..." No longer matches the vendor directory

Since go 1.5 introduced the vendor mechanism, the go package dependency problem has improved, but there is still a lot of room for the details of the vendor mechanism.

For example: We are in go test. , we expect to execute only our own code test, but the previous version of Go 1.9 will match the vendor directory under Repo and all the packages in the vendor directory will be executed once, taking the following repo structure as an example:

$tree vendor-matching/vendor-matching/├── foo.go├── foo_test.go└── vendor    └── mylib        ├── mylib.go        └── mylib_test.go

If we use go 1.8, then go test. The output is as follows:

$go test ./...ok      github.com/bigwhite/experiments/go19-examples/vendor-matching    0.008sok      github.com/bigwhite/experiments/go19-examples/vendor-matching/vendor/mylib    0.009s

As we can see, go test executes the test of the package under vendor. In this regard, gophers on go repo a lot of issue, but go team initially did not pay attention to this issue, but only to inform the following solution:

$go test $(go list ./... | grep -v /vendor/)

However, with the strong demands of the community, go team finally compromised and promised to fix the issue in Go 1.9. So in Go 1.9, you'll see the following results:

$go test ./...ok      github.com/bigwhite/experiments/go19-examples/vendor-matching    0.008s

The behavior that no longer matches the vendor directory is not confined to go test, but is applicable to all official go tools.

Iv. GC Performance

GC continues to optimize and improve in go 1.9, and most programs use 1.9 to achieve a certain level of performance improvement. 1.9 Release note specifically mentions the significant increase in the allocation performance of large memory objects.

In the "Go Runtime metrics" build article has been compared to several versions of the GC, from my figure in this case, go 1.9 and go 1.8 in the GC Latency Indicator Performance difference is not small:

V. Other

Here are some of the bits and pieces of Go 1.9, and here's what I'm interested in saying.

1. New Installation mode of Go 1.9

The Go 1.9 installation adds a new approach, with at least beta support, which is installed via go get&download:

# go get golang.org/x/build/version/go1.9beta2# which go1.9beta2/root/.bin/go18/bin/go1.9beta2# go1.9beta2 versiongo1.9beta2: not downloaded. Run 'go1.9beta2 download' to install to /root/sdk/go1.9beta2# go1.9beta2 downloadDownloaded 0.0% (15208 / 94833343 bytes) ...Downloaded 4.6% (4356956 / 94833343 bytes) ...Downloaded 34.7% (32897884 / 94833343 bytes) ...Downloaded 62.6% (59407196 / 94833343 bytes) ...Downloaded 84.6% (80182108 / 94833343 bytes) ...Downloaded 100.0% (94833343 / 94833343 bytes)Unpacking /root/sdk/go1.9beta2/go1.9beta2.linux-amd64.tar.gz ...Success. You may now run 'go1.9beta2'# go1.9beta2 versiongo version go1.9beta2 linux/amd64# go1.9beta2 env GOROOT/root/sdk/go1.9beta2

go1.9 env output supports JSON format:

# go1.9beta2 env -json{    "CC": "gcc",    "CGO_CFLAGS": "-g -O2",    "CGO_CPPFLAGS": "",    "CGO_CXXFLAGS": "-g -O2",    "CGO_ENABLED": "1",    "CGO_FFLAGS": "-g -O2",    "CGO_LDFLAGS": "-g -O2",    "CXX": "g++",    "GCCGO": "gccgo",    "GOARCH": "amd64",    "GOBIN": "/root/.bin/go18/bin",    "GOEXE": "",    "GOGCCFLAGS": "-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build750457963=/tmp/go-build -gno-record-gcc-switches",    "GOHOSTARCH": "amd64",    "GOHOSTOS": "linux",    "GOOS": "linux",    "GOPATH": "/root/go",    "GORACE": "",    "GOROOT": "/root/sdk/go1.9beta2",    "GOTOOLDIR": "/root/sdk/go1.9beta2/pkg/tool/linux_amd64",    "PKG_CONFIG": "pkg-config"}

2, Go Doc support to view the doc of the struct field

We use go 1.8 to view a field status for a struct response in the Net/http package:

# go doc net/http.Response.Statusdoc: no method Response.Status in package net/httpexit status 1

Go doc will get an error on going 1.8! Let's take a look at Go 1.9:

# go1.9beta2 doc net/http.Response.Statusstruct Response {    Status string  // e.g. "200 OK"}# go1.9beta2 doc net/http.Request.Methodstruct Request {    // Method specifies the HTTP method (GET, POST, PUT, etc.).    // For client requests an empty string means GET.    Method string}

3. Change of Core Library

A) increased monotonic clock support

In 2017 New Year's night, the European and American well-known CDN service provider CloudFlare's DNS has a large-scale failure, resulting in many European and American websites can not be accessed normally. Later, CloudFlare engineers analyzed the cause of the problem, the culprit is Golang time. Now (). The sub's measure of time uses only wall clock instead of monotonic clock, resulting in a negative return. The event that caused the exception is the leap second (leap second) that the New Year's Eve time-of-day organization adds in the full timeframe. In general, wall clock is used only to inform the time, Mnontonic clock is used to measure the passage of time. In order to fundamentally solve the problem, Go 1.9 in time package implemented with monotonic clock to measure the passage, this will not occur after the "negative passage" problem. This change does not affect the use of Gopher on the method level of the timer package.

b) Add Math/bits pack

In some algorithmic programming, it is often involved in the operation of bit bits. Go 1.9 Provides a high-performance math/bits package to address this issue. For BITS operations and algorithms, you can look at the classic "Hacker's Delight". This is not an example.

c) provides a map type that supports concurrency

Go native map is not goroutine-safe, although in the previous version has been added to the map concurrency detection and reminders, but once the gopher need to map, but also need to implement themselves. In Go 1.9, the standard library provides a Map type that supports concurrency: Sync.map. Sync. The use of map is relatively simple, here is a simple comparison of builtin map and sync. Map performance in concurrent environments:

We customize a primitive type of support concurrency: MYMAP, come with sync. Map to do the comparison:

 //Github.com/bigwhite/experiments/go19-examples/benchmark-for-map/map_benchmark.gopackage Mapbenchimport "sync" type MyMap struct {sync. Mutex m Map[int]int}var myMap *mymapvar syncmap *sync. Mapfunc init () {myMap = &mymap{m:make (map[int]int, +),} Syncmap = &sync. Map{}}func Builtinmapstore (k, v int) {Mymap.lock () defer mymap.unlock () mymap.m[k] = V}func Builtinmaplookup (k i NT) int {mymap.lock () defer mymap.unlock () if V, OK: = Mymap.m[k];!ok {return-1} else {RET        Urn v}}func builtinmapdelete (k int) {Mymap.lock () defer mymap.unlock () If _, OK: = Mymap.m[k];!ok { return} else {Delete (mymap.m, k)}}func Syncmapstore (k, v int) {Syncmap.store (k, v)}func Syncmaplookup (    k int) int {V, OK: = Syncmap.load (k) if!ok {return-1} return v. (int)}func syncmapdelete (k int) { Syncmap.delete (k)}  

For the above code, we write some concurrent benchmark test, using pseudo-random number as key:

// github.com/bigwhite/experiments/go19-examples/benchmark-for-map/map_benchmark_test.gopackage mapbenchimport "testing"func BenchmarkBuiltinMapStoreParalell(b *testing.B) {    b.RunParallel(func(pb *testing.PB) {        r := rand.New(rand.NewSource(time.Now().Unix()))        for pb.Next() {            // The loop body is executed b.N times total across all goroutines.            k := r.Intn(100000000)            builtinMapStore(k, k)        }    })}func BenchmarkSyncMapStoreParalell(b *testing.B) {    b.RunParallel(func(pb *testing.PB) {        r := rand.New(rand.NewSource(time.Now().Unix()))        for pb.Next() {            // The loop body is executed b.N times total across all goroutines.            k := r.Intn(100000000)            syncMapStore(k, k)        }    })}... ...

We execute the benchmark:

$go test -bench=.goos: darwingoarch: amd64pkg: github.com/bigwhite/experiments/go19-examples/benchmark-for-mapBenchmarkBuiltinMapStoreParalell-4         3000000           515 ns/opBenchmarkSyncMapStoreParalell-4            2000000           754 ns/opBenchmarkBuiltinMapLookupParalell-4        5000000           396 ns/opBenchmarkSyncMapLookupParalell-4          20000000            60.5 ns/opBenchmarkBuiltinMapDeleteParalell-4        5000000           392 ns/opBenchmarkSyncMapDeleteParalell-4          30000000            59.9 ns/opPASSok      github.com/bigwhite/experiments/go19-examples/benchmark-for-map    20.550s

As you can see, in addition to Store,lookup and delete two operations, sync. The map is much faster than my custom rough mymap, which seems to sync. Map has made a special optimization of read (a cursory look at the code: in the map read this block, sync. Map uses a lock-free mechanism, which should be the reason for fast.

d) Support for profiler labels

The general profiler does not always fully meet the requirements, and we often need to follow the "business-related" execution path to profile. Go 1.9 Adds support for the label in the Runtime/pprof package, go tool pprof tools. Go team member Rakyll has an article "Profiler labels in Go" detailing the use of profiler labels, which you can refer to here.

Vi. PostScript

While writing this article, Russ Cox has made the "the Future of Go" speech at the Gophercon 2017 Conference, and announce the opening of the Go2 curtain, although only calling on the world's gopher to help and plan Design and development of GO2. At the same time, the text version of the speech has been published on the Go official website, the article called "Toward Go 2", it is clearly a milestone in the evolution of the Go language time, it is worth every gopher to celebrate. But it will take some time, even a long time, for the Go2 boots to actually fall on the ground. Now, we still need to continue to use and improve Go1, let's start with Go 1.9 ^0^.

The demo code covered in this article can be downloaded here.

Weibo: @tonybai_cn
Public Number: Iamtonybai
Github.com:https://github.com/bigwhite

, Bigwhite. All rights reserved.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.