at yesterday's Go contributor annual summit, participants had a preliminary understanding of the error-handling and generic design drafts. The development of Go 2 was announced last year, and Google released the language update today.
For a quick overview of the content, see the video that Google played on Gophercon 2018:
As part of the Go 2 design process, Google has released these draft designs to inspire community discussion on the following three topics: Generics (generics), error handling, and error value semantics (err value semantics).
These draft designs are not a proposal in the sense of the GO proposal process. They are just a primer for discussion, and the ultimate goal is to give a good enough design and turn it into a practical proposal. Each draft design is accompanied by an "overview of the Problem", which is intended to: (1) Provide context, (2) Prepare for practical design documentation that contains more design details, and (3) facilitate discussion of the design framework and description. The issue overview provides background, goals, non-goals, design constraints, a brief summary of the design, a short discussion of the areas of focus, and a comparison with previous methods.
Again, these are just draft designs, not official proposals. There is no such proposal now. Google wants all users of go to help it improve the draft and refine it into a go proposal. To do this, Google created a wiki page to collect and organize feedback on each topic. Google wants users to help them update these pages, including adding users ' own feedback links.
Brief introduction
This overview and the accompanying details are part of the "Go 2 design Draft" (Go 2 Draft Designs) documentation. The overall goal of Go 2 is to provide the most important solution to the problem of go not being able to scale to a large code base and a large number of developers.
One of the reasons that Go programming does not scale successfully is error checking and the writing of error-handling code. Overall, the Go programming code checks for too many errors, but the code to handle these errors is very inadequate (explained below). The draft design is designed to address this problem by introducing a more lightweight error-checking syntax than the current customary "assignment and if Statement" (Assignment-and-if-statement).
As part of Go 2, Google also considered changing the semantics of the error values, which is a separate concern, but this document only involves error checking and handling.
Before go open source, members of the Go team-especially Ian Lance taylor---have been discussing the possible design of generics ( parametric polymorphism, parametric polymorphism). Google has learned from the experience of C + + and Java that the topic is so rich and complex that it will take a long time to think through and design a good solution. Instead of trying to do this, Google has spent time on features that are more directly applicable to the initial goal of Go network system software (now "cloud Software"), such as concurrency, extensible builds, and low-latency garbage collection.
After the go 1 release, Google continues to explore the many possible designs of generics. In April 2016, Google released these early designs (https://go.googlesource.com/proposal/+/master/design/15292-generics.md#). As part of the Go 2 re-entry "design mode", the Go team is again trying to explore the generics design, and wants generics to be integrated with the go language, providing users with enough flexibility and expression.
In the 2016 and 2017 Go user surveys, some form of generics is one of the most pressing two functional requirements (the other is package management). The Go community maintains a "go generic discussion summary" (Summary of Go generics discussions) documentation.
Many people mistakenly assume that the Go team's position is that "go will never have generics." But this is not true, Google knows the potential of generics, it can make Go more flexible, powerful and complex. If you want to add generics, Google wants to try to increase its agility and make it more powerful without adding to the Go complexity.
Error Handling: Problem overview
To scale to a large code base, the GO program must be lightweight, without undue repetition, and robust enough to gracefully handle errors that occur.
In the Go design, we consciously choose to use explicit error results and error checking. The C language typically uses explicit checks for implicit error results, while exception handling in many languages (including C + +, C #, Java, and Python) represents implicit checking of implicit results.
Goal
For go 2, we want to make error checking more lightweight and reduce the amount of Go program text used for error checking. We also want to make it easier to write programs that handle errors and to improve the likelihood of programmers handling errors.
Error checking and error handling must be explicit, which is visible in the program text. We don't want to repeat the flaw in exception handling.
The existing code must be able to continue running and be as effective as it is now. Any change must be able to interoperate with existing code.
As mentioned earlier, the goal of the design is not to change or enhance the semantics of the error.
Error value: Problem overview
Large programs must be able to test errors and respond programmatically, and report these errors.
Because the error value is any value that implements the error interface, there are four traditional ways to test for specific errors in the Go program. One, the program can use Sentinel error (such as IO. EOF) to test their equivalence. Second, the program can use type assertions or type switch to check the error implementation type. Third, point-to-point checking (such as OS. isnotexist) Check for specific kinds of errors and make limited unpacking. Four, because these methods usually do not work when the error is encapsulated in an additional context, the program is usually in err. Error () is reported as a substring search in the wrong text. Obviously, the last method is the least desirable, even in the case of arbitrary encapsulation, it is better to support the first three methods.
Goal
We have two goals, which correspond to two major issues respectively. One, we want to make the process of checking the program error simpler, with fewer errors, which improves error handling and the robustness of the real program. Second, we want to print out errors with additional details in the standard format.
Any solution must be able to make existing code work properly and fit into an existing source tree. In particular, you must preserve the use of error Sentinel (such as IO. errunexpectedeof) compares the concepts of equality and testing for specific kinds of errors. Existing error Sentinel must continue to be supported, and existing code does not have to be changed to return different error types. An extension function, such as an OS. Ispermission) to understand the arbitrary package rather than the fixed set is feasible.
When considering solutions for printing additional error details, we prefer to use golang.org/x/text/message to make positioning and translation errors possible, or at least to avoid impossibility.
The package must continue to easily define its error type. Defining a new generic "real error implementation" is unacceptable, and using this implementation requires all the code. Adding a lot of additional requirements to error implementations is unacceptable, and these error implementations involve only a few packages. Errors must also be created efficiently. The error is not an exception. It is common to generate, process, and discard errors during a program's run.
Many years ago, a program written by Google in an exception-based language (exception-based) was found to have been generating exceptions. Finally, the function on the deep nested stack tries to open each path in the fixed list of file paths to find the configuration file. Each failed open operation causes an exception, and the generation of the exception wastes a significant amount of time to record the deep execution stack, after which the caller discards all of the work and continues the loop. Error generation in Go code must maintain a fixed cost, regardless of stack depth or other context. (deferred handlers run before the stack is undone for the same reason: handlers that care about the stack context can check the active stack without expensive snapshot operations.) )
Generics: An overview of issues
In order to promote the large code base of the Go language and the contribution of the developer, it is very important to improve the reusability of the code. In fact, the early focus of the Go language is simply to make sure that programs that contain many independent packages are quickly built, so the cost of reusing code is not very high. One of the key features of the Go language is the way it interfaces, which is also directly positioned to improve code reusability. Specifically, this interface can write an abstract implementation of an algorithm to eliminate unnecessary detail. For example, Container/heap is in the heap. The Interface operation provides the algorithm for heap maintenance (heap-maintenance) in the form of a normal function, which makes container/heap suitable for any standby storage, not just some values. These properties of the interface make Go very powerful.
At the same time, most programmers wishing to get priority sequences do not want to implement the underlying storage for the algorithm, and then call the heap algorithm. These programmers prefer to let the implementation manage its own array, but Go does not allow Type-safe to express it. The closest is to create a priority sequence of interface{} values and use type assertions after each element is fetched.
Polymorphism becomes more than just a data container. We may want to implement many general-purpose algorithms as naïve functions that can apply various types, but the functions we write in Go now apply only to a single type. An example of a generic function might be as follows:
// Keys returns the keys from a map.func Keys(m map[K]V) []K// Uniq filters repeated elements from a channel,// returning a channel of the filtered data.func Uniq(<-chan T) <-chan T// Merge merges all data received on any of the channels,// returning a channel of the merged data.func Merge(chans ...<-chan T) <-chan T// SortSlice sorts a slice of data using the given comparison function.func SortSlice(data []T, less func(x, y T) bool)
Goal
Google's goal is to solve the problem of writing the Go language library with parameter polymorphism with type parameters , which abstract out unnecessary type details (as described above).
In addition to the expected container type, Google also wants to write useful libraries to manipulate arbitrary map and channel values, and the ideal solution is to write polymorphic functions that can be manipulated on []byte and string values.
Allowing other types of parameterization is not a goal for Google, for example, by using constant values for parameterization . It is also not a goal to allow a proprietary implementation of polymorphic definitions, such as using a bit wrapper (bit-packing) to define a generic vector<t> and a specific vector<bool>.
We want to learn from the generic issues of C + + and Java. In order to support software engineering, the generics of the Go language must explicitly record the constraints on the type parameters as a clear mandatory agreement between the caller and the implementation. But it is also important for the compiler to report explicit errors when the caller does not satisfy these constraints or the implementation itself is beyond the constraints.
In the absence of tricky special circumstances and without exposing the implementation details, the polymorphism of the Go language must be adapted smoothly to the environment language. For example, it is unacceptable to limit the type parameter to cases where the machine is characterized as a single pointer or a single word. Another example of this is that once the Universal Keys (map[k]v) []k function is initialized to K=int and v=string, it must be semantically treated identically to the handwritten non-generic function. In particular, it must be assignable to type variable func (map[int]string) []int.
The polymorphism in the Go language should be implemented at compile time and run time, so the decision to implement the policy can also be used for the compiler and be treated equally with any other compiler optimizations. This flexibility will solve the generics dilemma. The Go language is largely an intuitive and easy-to-understand language that must be preserved if we are to add polymorphism.
Reference content:
Https://go.googlesource.com/proposal/+/master/design/go2draft.md
https://news.ycombinator.com/item?id=17859963