This is a creation in Article, where the information may have evolved or changed.
The Go Core project team released the Go 1.4 Beta1 version earlier this month after the go 1.3 release six months ago. Although this version of the change point is not revolutionary, but for the subsequent development of the go language, laid the foundation, set the tone. Here are a few interesting points of change combined with Go 1.4 code for some simple description, I hope you can have a perceptual understanding of Go 1.4.
Go 1.4 still retains the promise of Go 1 compatibility, and your existing code can be compiled and run with Go 1.4 with almost no changes. (Here's my test environment: Go version go1.3 darwin/amd64 vs. go version go1.4beta1 linux/amd64)
First, language changes
1. For-range Cycle
In Go 1.3 and before, the For-range Loop has two forms:
For k, V: = range x {
...
}
And
For k: = range x {
...
}
Problem: If we don't care about the value in the loop, we only care about the loop itself, we still have to provide a variable, or use _ placeholder.
For _ = range x {
...
}
The following syntax is not compiled on Go 1.3 and previously:
For range x {
...
}
However, go 1.4 supports this form of syntax, which makes the code cleaner, although it may rarely be used.
Example:
Testforrange.go
Package Main
Import "FMT"
Func Main () {
var a [5]int = [5]int{2, 3, 4, 5, 6}
For k, V: = Range a {
Fmt. Println (k, v)
}
For k: = Range A {
Fmt. Println (k)
}
For _ = Range a {
Fmt. Println ("Print without care about the key and value")
}
For range A {
Fmt. Println ("New syntax–print without care about the key and value")
}
}
Go 1.3 Compilation Error:
$go Run Testforrange.go
# command-line-arguments
./testforrange.go:19:syntax error:unexpected Range, expecting {
./testforrange.go:22:syntax error:unexpected}
Go 1.4 compiles successfully and outputs the correct results:
0 2
1 3
2 4
3 5
4 6
0
1
2
3
4
Print without care about the key and value
Print without care about the key and value
Print without care about the key and value
Print without care about the key and value
Print without care about the key and value
New syntax–print without care about the key and value
New syntax–print without care about the key and value
New syntax–print without care about the key and value
New syntax–print without care about the key and value
New syntax–print without care about the key and value
2. Call method by **t
The following example:
Package Main
Import "FMT"
Type T int
Func (T) M () {
Fmt. Println ("Call M")
}
var x **t
Func Main () {
X.M ()
}
According to the official release note of Go 1.4, the 1.3 version and the previous GC and GCCGO will normally accept this call method. However, the Go 1 specification allows only one dereference to be automatically preceded by X, not two, so this is a violation of the definition. Go 1.4 enforces the prohibition of such calls.
But according to my actual test, go 1.3 and go 1.4 will have the same compilation error for the above code.
$go Run Testdoubledeferpointer.go
# command-line-arguments
./testdoubledeferpointer.go:14:calling method M with receiver X (type **t) requires explicit dereference
Ii. supported operating systems and changes in processor architectures
This cannot be demonstrated. A major change, though, is that go 1.4 can build a binary program that runs on an ARM processor's Android operating system. Using the support package in the Go.mobile Library, Go 1.4 can also build a. So library that can be loaded by Android apps.
Third, compatibility changes
People bypass the constraints of the Go language type system through unsafe packages and using the internal implementation details of go and the machine representation of the data. Go's designers consider this to be disrespectful to the Go compatibility specification, and in Go 1.4, the Go Core group formally declares that unsafe code no longer guarantees compatibility. This time go 1.4 did not make any code changes for this, just a clarification.
Iv. changes in implementation and tools
1. Changes in runtime (runtime)
Go 1.3 and previous versions, the Go Language runtime (garbage collection, concurrency support, interface management, maps, slices, strings, etc.) is mainly implemented by C and a small number of assembly languages. In version 1.4, many of the code was replaced with go itself, so that the garbage collector could scan the program runtime stack for accurate information about active variables. This varies greatly, but there should be no semantic impact on the program.
This rewrite makes the garbage collector more precise, which means that it knows the location of active pointers in all programs. These related changes will reduce the size of the heap, reducing the overall 10%~30%.
The result is that the stack is no longer required to be segmented (segmented), eliminating the "hot split" problem. If a stack reaches the usage limit, go assigns a new, larger stack, and all active stack frames in the corresponding goroutine will be copied to the new stack, and all pointers to the stack will be updated. In some scenarios, the performance will be significantly improved, and with this modification, its performance is more predictable.
The use of continuous stacks (contiguous stacks) makes the initial size of the stack smaller, and the initial stack size of goroutine in Go 1.4 is reduced from 8192 bytes to 2048 bytes. (The official release may be changed to 4096).
The implementation of the interface value type has also been adjusted. In the previous release, the interface value was internally hosted in one word (word), either as a pointer, or as a pure measure of the size of a single word (One-word), depending on what object was specifically stored in the interface value variable. This implementation poses a lot of difficulties for the garbage collector, so the interface values are represented internally in the Go 1.4 release. In a running program, the vast majority of interface values are pointers, so this effect is minimal. However, programs that store integer values in interface value type variables will have more memory allocations.
2, the state of GCCGO
The release plan for GCC and go two projects is not synchronous, and the GCC 4.9 version contains the GCCGO that implements the 1.2 specification, and the next release of GCC 5.0 will likely contain the GCCGO that implements the 1.4 specification.
3. Internal Bag (internal package)
Go takes the package as the basic logical unit to organize the code. Go 1.3 and previous versions of the Go language actually only support the visibility of the symbols in both forms of the package: local (unexported) and global (exported). There are times when we want packages to be imported and accessed by their "near" packages instead of being imported by all external packages. But the previous go language does not have this feature. Go 1.4 introduces the concept of the "internal" package, and the rules for importing this internal package are as follows:
If the import code itself is not in the directory tree rooted in the parent directory of the "internal" directory, its import path (imported path) is not allowed to contain the internal element.
For example:
–a/b/c/internal/d/e/f can only be imported from the code under the directory tree rooted in a/b/c, and cannot be imported under a/b/g code.
– $GOROOT/src/pkg/internal/xxx can only be imported by code in the standard library ($GOROOT/src). (Note: Go 1.4 cancels the $goroot/src/pkg and the standard library is moved to $GOROOT/SRC).
– $GOROOT/src/pkg/net/http/internal can only be imported by Net/http and net/http/* packages
– $GOPATH/src/mypkg/internal/foo can only be imported by the code of the $GOPATH/SRC/MYPKG package
For Go 1.4 The rule is first enforced under $goroot. Go 1.5 applies the extension to $gopath.
4, authoritative Import path (import paths)
We often use code that is hosted in a common code hosting service, such as github.com, which means that the package import path contains the managed service name, such as Github.com/rsc/pdf. Some scenarios in order to not destroy the user code, we use Rsc.io/pdf, shielding the underlying specific hosting services, such as rso.io/pdf may be behind the github.com may be bitbucket. But this introduces a problem that inadvertently we generate two legitimate import paths for a package. If the two legitimate paths are used in a program, programs that use the old import path package will get an error once the path is not recognized for updates, or if the package is migrated to another different managed public service.
Go 1.4 introduces a comment for a package that identifies the authoritative import path for this package. If the imported path used is not an authoritative path, the Go command rejects the compilation. The syntax is simple:
Package PDF//import "Rsc.io/pdf"
If the PDF portfolio uses authoritative import path annotations, programs that attempt to import paths using github.com/rsc/pdf will be rejected by the go compiler.
This authoritative import path check is done at compile time, not the download phase.
Let's give an example:
Our package Foo was previously placed under Github.com/bigwhite/foo, and then the main escrow station was replaced with the Tonybai.com/foo, the latest Foo package code:
Package foo//import "Tonybai.com/foo"
Import "FMT"
Func Echo (a string) {
Fmt. Println ("Foo:, a)
}
An app imported the package through the old path Github.com/bigwhite/foo:
Testcanonicalimportpath.go
Package Main
Import "Github.com/bigwhite/foo"
Func Main () {
Foo. Echo ("hello!")
}
We compile the go file and get the following results:
Code in Directory/home/tonybai/test/go/src/github.com/bigwhite/foo expects import "Tonybai.com/foo"
5, go generate sub-command
Go 1.4 in the Go Tool collection introduces a NEW subcommand: go generate, used to automate the generation of certain types of code before compiling. For example, run the Yacc compiler on. Y to generate the. Go source file that implements the syntax. Or use the Stringer tool to automatically generate a string method for a constant. This command is not executed automatically by Go tools (build, get, etc.) and must be performed explicitly.
But I tested it briefly and it seems that this command is in the design document:
+build Generate
It's not good. Even if you put it as generate directive into the go source file, the file will still be compiled by the go compiler as a normal go file. The Go 1.4 standard library uses go generate directive with three locations:
Strconv/quote.go://go:generate Go run makeisprint.go-output isprint.go
Time/zoneinfo_windows.go://go:generate Go run genzabbrs.go-output zoneinfo_abbrs_windows.go
Unicode/letter.go://go:generate Go run maketables.go-tables=all-output tables.go
Using go generate to achieve generics (generics) does not seem so elegant. Although the designer does not use it as a go generic implementation ^_^.
6, the source code layout changes
In the Go own repository ($GOROOT), the source code of the package is in src/pkg, which differs from other libraries, including the go own sub-library, such as Go.tools. So in Go 1.4, the PKG Layer directory tree will be removed, such as the FMT package source has been placed under the SRC/PKG/FMT, now placed under the SRC/FMT.
Five, performance
Most programs that use 1.4 compile will run at or slightly faster than 1.3, and some may become slower. This modification is more difficult to predict accurately.
This time, many runtime codes change from C to go, which will result in some heap size reductions. In addition, this facilitates go compiler optimizations, such as inline, which can bring a slight performance boost.
The garbage collector is accelerated on the one hand, allowing the heavily dependent garbage collection program to gain measurable gains. But on the other hand, the new write barrier has caused performance degradation. The amount of ascension and descent depends on the behavior of the program.
, Bigwhite. All rights reserved.