Go Language Design pattern Practice: iterators (Iterator)

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

About this series

decided to open a new hole.

This series is first about the go language practice. The actual use of the go language in the project also has a period of time, an experience is whether it is official documents, books or web materials, about the go language idioms (idiom) Introduction are relatively small, basic can only rely on the standard library source code to ponder their own, so I particularly want to have some collection and summary.

Then the series is about design patterns. Although the go language is not an object-oriented programming language, many object-oriented design patterns need to solve the problem that exists in the programming. No matter what language, always have to face and solve these problems, but the solution of the ideas and ways will be different. So I want to use the classic design pattern as a starting point to expand this series, after all, we are familiar with the design patterns, you can avoid out of nowhere to come up with some crappy application scenarios.

The specific topics in this series will be more flexible, including the topics of the program:

    1. Go language idiomatic method.
    2. The implementation of the design pattern. In particular, the introduction of closures, Ducktype, and other language features brought about by the changes.
    3. The discussion of design pattern thought. There will be some spit slots.

Scenarios that do not use iterators

the first thing to point out is that in most cases go programs don't need iterators. because the built-in slice and map two containers can be traversed by range, both containers are sufficiently optimized for performance. As long as there is no special requirement, the two containers are usually used directly to solve the problem. Even if you have to write a custom container, we can almost always implement a function that copies all the elements (references) back to a slice, so that the caller can iterate directly with range.

Of course, some special occasions iterators still have a place to play. The next () iterator, for example, is a time-consuming operation that can not copy all elements in one breath, or, for example, interrupt traversal in some conditions.

Classic implementations

Classic implementation completely adopts object-oriented thinking. To simplify the problem, the following example container is simple []int , we are in main function uses iterators for traversal operations and prints the values that are taken, and the interface design of the iterator references Java.

 PackageMainImport "FMT"typeInts []intfunc(I Ints) First () Iterator {returnIterator{data:i,index:0,}}typeIteratorstruct{Data Intsindexint}func(I Iterator) Get ()int{returnI.data[i.index]}func(I Iterator) Hasnext ()BOOL{returnI.index <Len(I.data)}func(I Iterator) Next () Iterator {returnIterator{data:i.data,index:i.index +1,}}funcMain () {ints: = INTs{1,2,3} forit: = INTs. First (); It. Hasnext (); it = it. Next () {fmt. Println (it. Get ())}}

Closure implementation

The Go language supports first class functions, higher order functions, closures, and multiple return value functions. Using these features, you can implement iterators in a different way.

At first glance, the closure implementation is completely different from the classical implementation, in fact, in essence, the two differ little. In the classic implementation, the data required by the iterator exists in the struct,Get() HasNext() Next()Three functions defined asIteratormethod to bind to data; The iterator in the closure implementation is an anonymous function that requires the datai IntsAndindexBound in the form of closure up value, the two values returned by the anonymous function correspond exactly to those in the classic implementation.Get()AndHasNext()

 PackageMainImport "FMT"typeInts []intfunc(I Ints) Iterator ()func() (int,BOOL) {Index: =0return func() (ValintOkBOOL) {ifIndex >=Len(i) {return}val, OK = I[index],trueindex++return}}funcMain () {ints: = INTs{1,2,3}it: = INTs. Iterator () for{val, OK: = It ()if!ok { Break}fmt. Println (val)}}

Channel implementation

This implementation is the most go-to, using a channel in the new Goroutine the container elements in turn output. The advantage is that the channel can be received with range, so the caller code is very concise, the disadvantage is that the goroutine context switch will have overhead, this implementation is undoubtedly the least efficient, in addition to the caller must receive all the data, if only half of the interrupt sender will be blocked forever.

Vaguely remember in the mailing list to see that the standard library has the use of this example, just went over the next did not find the original posts:-)

By the way, "creating a channel in a function returns, while creating a goroutine to channel the data" This is an important idiom (although I don't know what this should be called.) =), can be used to do sequence generators, fan-out, fan-in and so on.

 PackageMainImport "FMT"typeInts []intfunc(I Ints) Iterator () <-Chan int{c: = Make(Chan int)Go func() { for_, V: =RangeI {c <-v}Close(c)} ()returnCfuncMain () {ints: = INTs{1,2,3} forV: =RangeINTs. Iterator () {fmt. Println (v)}}

do Implementation

This iterator implementation is the most concise, the code is very straightforward, needless to say. If you want to add the interrupt iteration function, you can func (int) changed to func (int) bool , do, depending on the return value, determines whether to exit the iteration.

Examples of the container/list use of Do () in the standard library.

Package MainImport "FMT"TypeInts[]intfunc(IInts) Do(FN func(int) ) { for _, V: = Range I {fn (v)}}funcMain () {ints: =Ints{1,2,3}ints. Do( func(v int) {FMT.Println(v)})}

Summarize

    1. There is no class or inheritance in the go language, and it does not have the ability to fully express object-oriented, and is not an object-oriented language in the usual sense. But this does not prevent the go language to implement object-oriented thinking, using its language features, to achieve encapsulation, composition, polymorphism are no problem.
    2. The essence of design patterns is the idea rather than the class diagram. Programming language is in continuous progress, the class diagram has been a few decades ago that one, put aside the class diagram to re-examine the problem, reasonable use of new language features can be more concise design pattern implementation.
Classification:  Go Language Design pattern practice
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.