Comment: Why I don't like the Go Language interface

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


Recently in the Go Language QQ group to see about the Turing community has cattle man Lao Zhao Spit Groove Xu Xiwei "Go language programming" various arguments.



I have also seen the old Zhao Spit trough Xu Xiwei "Go language Programming" article, at that time want to Lao Zhao if can make big book in insufficient part complement perfect is also a good thing. Therefore, the old Zhao's follow-up article is very look forward to.



Who knows the old Zhao after the two article Spit Groove Go language article, found that is not the case at all, the content of The spit groove is too far.
Originally did not want to mix in, but see QQ Group and Turing community there are many people even the old Zhao's article as the truth.
Really can't help, yesterday registered account, come in also say my point of view.



Here are a few articles from Lao Zhao:


    • Go is a bright language, the old man is a bull, but this book is quite general
    • Why do I think that goroutine and channel are built into the language of the functions of the class library on other platforms?
    • Why I don't like the Go Language interface (ie structural Typing)


This article is available at the Turing Community website:


    • http://www.ituring.com.cn/article/37642


Additional notes:



Because the current article is mainly aimed at the old Zhao does not like the Go Language interface do
Comments. Because of the title of the reason, also caused a great controversy (because many people say I understand a lot of views and Old Zhao's original text does not match).



I'll introduce some of the features of the go language later, but it won't be the way it is now.


The so-called Go Language interface, is not to display the declaration type T implementation of interface I, as long as the public method of type T fully meet the requirements of interface I, you can put the object of type T is where the interface I need. The scientific name of this practice is called structural Typing, and some people consider it as a static duck Typing. In addition to the go interface, there are similar things like Scala's traits and so on. Some people think this feature is good, but I personally do not like this approach, so here to talk about its shortcomings. Of course, this is similar to the discussion of static language in dynamic language, which cannot be easily and rudely the next "good" or "bad" conclusion.


Original view:


    • The implicit interface of Go is actually the static duck Typing. Many languages (mainly dynamic languages) have long been available.
    • static types and dynamic types are not absolutely good and bad.


My point of view:


    • Go's implicit interface duck typing is really not a new technology, but it should be very rare to support duck typing in mainstream static programming languages (it is unclear if there is currently only go language support).
    • Static type and dynamic type although there is no absolute good and bad, but each has its own advantages, no one can do everything. While go is an attempt to combine static types and dynamic types (interface) with their respective advantages.

So start from the beginning: What is an interface. In fact, in layman's terms, an interface is a protocol that specifies a group of members, for example. NETICollectioninterface:

public interface ICollection {
   int Count { get; }
   object SyncRoot { get; }
   bool IsSynchronized { get; }
   void CopyTo(Array array, int index);
}

Is this all about an agreement? This is not the case, in fact the interface also specifies the "characteristics" of each behavior. For example, this interface, inCountaddition to returning the number of elements in the collection, implies that it needs to return this requirement in O (1) time. Such a method of using theICollectioninterface can be used with confidence to use theCountproperty to get the size of the collection, in order to know these characteristics of the correct algorithm to write the program, without worrying about performance problems, this can achieve so-called "interface-oriented programming." Of course, this "feature" does not refer to "performance", for example, itCountalso contains a seemingly natural hiding requirement such as "Do not modify the contents of a collection," which isICollectionpart of the protocol.


Original view:


    • An interface is a protocol that specifies a set of members.
    • The interface also specifies the "characteristics" of each behavior corresponding to the time complexity.
    • The interface also specifies that each behavior also contains the hidden requirements for whether the collection will be modified.


My point of view:


    • The first article: Nothing to explain, should be the common meaning of the interface.
    • The second article: But the interface also contains the time complexity of the "feature" is compared to pull. Will this feature be constrained by language characteristics (how is language constrained?), or is it just a supplement to the interface's documentation (which is the language feature)?
    • Article three: This is still a spit slot to the point. The Go interface does not support C + + similarconstadornments, except that the method outside of the interface is not supported (The Goconstkeyword is another semantics).


But is it really safe to have it in C + +const?


class Foo {
     private: mutable Mutex mutex_;

     public: void doSomething () const {
         MutexLocker locker (& mutex_);
         // const has been bypassed
     }
};


The only use of method adornments in C + +constis to increase the number of compilation hassles and to make no commitment to the user. The user is more concerned aboutdoSomethingwhat to do, the above method actually andvoid doSomethingConst()to express the meaning of the similar.



Whether it is a static library or a dynamic library, which one can guarantee a function from the library level can not do? If the C + +constkeyword does not
True assuranceconst, while similar implementation details (including the previously mentioned and time-complexity-related performance features) must be supplemented by documentation.
What form should the document provide (code comments?). Word document? Other format documents?)? Are there really many of these documents that make sure everyone is watching?
The document is only a direct verbal agreement, if the document is really so good (and implementation), then assembly language can also solve all problems.



How does the Go language solveconstand performance problems?



First of all, for C language function parameter value of the semantics,constis the inevitable result.
However, if the parameter is too much to consider performance, it will be considered to pass the pointer (or the semantics of the value of the transfer), through the pointer can not be guaranteedconstsemantics. How can you trust the information that it provides to the header file if you can't even trust the library function you're usingconst?



Because,constand performance is contradictory. If you want to be absolutely safe in the go language, pass the value. If you want performance (or return side effects),
Then pass the pointer:


type Foo int

// want performance
func (self * Foo) Get () int {
     return * self
}
// be safe
func (self Foo) GetConst () int {
     return self
}


How does the go language deal with performance issues (and unit test issues)? The answer is the Integrationgo testTest tool. The test code in the Go language ispackage mainan integral part of the pkg. Not only is the ordinary pkg possiblego test,package mainbut also can be usedgo testfor testing.



We add unit tests and performance tests to the previous code.


// foo_test.go

func TestGet(t *testing.T) {
    var foo Foo = 0
    if v := foo.Get(); v != 0 {
        t.Errorf("Bad Get. Need=%v, Got=%v", 0, v)
    }
}
func TestGetConst(t *testing.T) {
    var foo Foo = 0
    if v := foo.GetConst(); v != 0 {
        t.Errorf("Bad GetConst. Need=%v, Got=%v", 0, v)
    }
}

func BenchmarkGet(b *testing.B) {
    var foo Foo = 0
    for i := 0; i < b.N; i++ {
        _ = foo.Get()
    }
}
func BenchmarkGetConst(b *testing.B) {
    var foo Foo = 0
    for i := 0; i < b.N; i++ {
        _ = foo.GetConst()
    }
}


Of course, the final test results are still for people to see. If the creator/user intentionally destroys, then the good tool also can not be able.


We can also explain some other problems, such as why. NET list is not called ArrayList, of course these are just my speculation. My idea is that because the list and the IList interface are the same, and some methods like IList, such as the indexer requirements can quickly get the elements, so the method of using the IList interface can use the subscript to access with confidence, and the data structure satisfies the characteristics of the basic and array is difficult to give up, So the array in the name seems a little superfluous.

If the list is renamed ArrayList, then it seems to imply that IList can have other implementations, is it linkedlist? In fact, LinkedList has nothing to do with IList, because its features and list are too different, it has some addfirst, insertbefore methods and so on. Of course, LinkedList and list are ICollection, so we can safely use a few of them, and their behavioral characteristics are clear.


Original view:


    • Speculation: Because there isIList<T>a reason for the interface, it is notList<T>namedArrayList<T>.
    • BecauseIList<T>(this is supposed to be a clerical error, I think the author is sayingList<T>) indexers require the ability to get elements quickly, so that the IList interface approach can be safely accessed using subscripts (the algorithm's complexity features are passed to the interface direction).
    • Another reason that cannot beList<T>changedArrayList<T>isLinkedList<T>. Because it isList<T>LinkedList<T>not the same as the time complexity, it cannot be an interface (presumably an interface meaning of an algorithmic complexity).
    • LinkedList<T>AndList<T>all belong toICollection<T>this ancestor interface.


My point of view:


    • Article One: I don't know how the original author speculated. The intention of the interface is to separate from the implementation. Now it's all tied together, so what else does the interface do (one forXxx<T>anIXxx<T>interface)?
    • The second: Because the runtime to the interface passed a time complexity of the implementation, it is deduced that the interface conforms to some kind of time complexity, the logic simply does not pass!
    • Article three: With the first two similar meaning, there is nothing to say.
    • Fourth: This should be the advantage of go non-intrusive interface. C++/java is because of the intrusion of the interface, which led to the interface and implementation can not be completely separated. Because, C++/java most of the time in the interface/implementation between the ancestors of the relationship between the eight generations (important is not how to classify, but what can be done). You can refer to the Java example given by Xu Xiwei (it is really important to understand the relationship between fathers and eight generations): Http://docs.oracle.com/javase/1.4.2/docs/api/overview-tree.html.

One of the reverse cases in this regard is java. In the Java class Library, both ArrayList and LinkedList implement the list interface, all with the Get method, passing in a subscript, returning the element in that position, but the two implementations are time consuming O (1) and the latter is time consuming O (N), both large and close to the court. Well, now I'm going to implement a method that requires starting with the first element and returning the elements from every P-position, can we also program for the list interface? If we rely on subscript access, the time complexity of the algorithm is changed from the desired O (n/p) to O (n2/p) when the external accidentally passes in LinkedList. If we choose to traverse the entire list, even ArrayList we can only get the efficiency of O (N). In other words, the Java class Library list interface is a joke, even the stack class has implemented the list, I do not know how the designers were thinking.

Simply put, "interface-oriented programming" has no meaning if the interface does not guarantee behavioral characteristics.


Original view:


    • JavaArrayListLinkedListimplementsListinterfaces, butgetthe time complexity of the methods is different.
    • If the interface does not guarantee behavioral characteristics, then "interface-oriented programming" is meaningless.


My point of view:


    • Article one: This is actually a premise of the original author, is to introduce the conclusion of the second article. However, I think the logic here is also problematic. This example only shows that the interface has its shortcomings, but how does it prove that "interface-oriented programming" is meaningless ?
    • Article two: I want to ask, why do I have to use the interface here (is it a C++/java object-oriented brainwashing)? The interface has its proper place (oriented to the logical level), and there is an inappropriate place (for the underlying algorithm level). Why not use it directly hereArrayListorLinkedList?

The Go Language interface also has a similar problem, because structural typing only from the surface (member name, parameter number and type, etc.) to understand an interface, do not pay attention to the interface rules and meaning, also can not check. Forget it's Coursera. In which course, one example is mentioned:

Interface IPainter {
    void Draw();
}

nterface ICowBoy {
     void Draw();
}

Draw also has the meaning of "drawing" and "pulling the gun" in English, so both the painter (Painter) and the Cowboy (Cow Boy) can have draw, but the meaning of the two is very different. If we achieve a "xiaoming" type, he is obviously just a painter, but we let him go to fight with other cowboys, it is tantamount to let him go to die. On the other hand, "Xiao Wang" can be both a "painter" is also a "cowboy", he two draw will, in C # we can put him into:

class XiaoWang: IPainter, ICowBoy {
     void IPainter.Draw () {
          // draw
     }

     void ICowBoy.Draw () {
          // draw a gun
     }
}

So I've never understood Java's trade-offs. You say such an emphasis on the object-oriented emphasis on the design of the interface language, but also the mandatory exception, how do not support the display implementation of the interface?


Original view:


    • Different implementations haveDrawdifferent meanings, so interfaces are best able to support different implementations.
    • Interfaces such as Java/go are not as powerful as C # interfaces.


My point of view:


    • The first: Do not because you have a hammer, you put everything as nails! This is a C # example (I don't understand C #), but please don't put it in the go language! Before C + + had a function overload (semantically or similarly, but with different signatures), I did not expect C # to have a feature that supports the same word in different meanings.
    • Article two: can only say the original author really does not understand the go language.


Why doesn't the go language support these fancy features? Because, they are too complex and useless, the code written poorly understood (if the original author does not prompt, who can findDarwthe different meanings of this pit?). The philosophy of the Go language: "Less is more!".



See what the Go language does:


type Painter interface {
    Draw()
}
type CowBoyer interface {
    DrawTheGun()
}

type XiaoWang struct {
    // ...
}

func (self *XiaoWang)Draw() {
    // ...
}
func (self *XiaoWang)DrawTheGun() {
    // ...
}


XiaoWangWhat you need to care about is just what you have (method), as far as ancestral relationships are concerned.
By the time the featuresXiaoWangmature and stable, it is found that the new comes withXiaoMingsimilar functional features,
This is the time to consider how to use interfaces to describeXiaoWangandXiaoMingshare features.


That's why I'm more inclined to explicitly label exceptions in Java and C #. Because the program is written by people, it is not because a class simply exists because there are some members, it will be used as some interface, and everything is "designed" rather than naturally occurring. It's like we're not going to be a woman in Thailand because it looks like a beautiful person, and the makeup and PS technology is horrible these days.


Original view:


    • Interfaces are "designed" rather than naturally occurring.
    • There is a shortage of interfaces because in Thailand it is not possible to美女infer this type of person based on this interface女人.


My point of view:


    • Go philosophy is to construct specific objects, and then gradually summed up the interface according to the generality, at first do not care about the relationship between the ancestors of the eight generations.
    • Then女人how is it defined, isn't this an interface?

I am here again the heart of the villain: I guess someone will see here that I'm just sour grapes, because C # does not have this feature so that it is not good. This is not true, as early as I did not hear structural typing this scientific name when the question was considered. I have written an auxiliary method that converts any type into an interface, for example:

XiaoMing xm = new XiaoMing();
ICowBoy cb = StructuralTyping.From(xm).To<ICowBoy>();

So, we are very happy to only understand the painting of Xiaoming sent to the duel. The internal implementation principle is simple, just using emit to dynamically generate a wrapper class at run time. In addition, I use theMono.Cecilparse assembly after compilation to checkFromif theTogeneric parameter matches, which also provides a static check of the compile period. In addition, I support covariant contravariance, and also allow interface methods that do not require a return value to be compatible with methods that have return values, which is much better than simply judging by name and parameter type.


Original view:


    • This feature of the C # interface is very NB ...


My point of view:



Let's see how Go is written (based on the previous go code, withoutDrawoverloading):


var xm interface{} = new(XiaoWang)cb := xm.(Painter).(CowBoyer)


But, I think this kind of portrait is very abnormal. The go language is designed to solve practical engineering problems,
Not to be a hodgepodge of NB technologies like C + +.



I always agree with the idea that any language can write garbage codes, but it is not possible to use these garbage codes to prove that the original language is rubbish.


With a variety of options, I was relieved to say which one I liked. JavaScript can only write code with callbacks, so many people say that it is the advantage of JavaScript, saying that the callback how wonderful I would deeply disagree-just can't resist to start enjoying it ...

This article seems to be a bit of a lot of vomit? But this little article is pretty cool.


This section is not interface-related, too lazy to tidy/spit groove.



Finally, I just want to say an example of a function that is popular from the C language ageprintf.
Let's see what the Go language looks like (fmt.Fprintf):


func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)


In the go language,fmt.Fprintfonly care about how to identify the variousa ...interface{}, how format these parameters,
As for how to write, where to write where to go that'sw io.Writerthe whole thing.



The first parameter herew io.Writeris an interface, which can be written not only, but also can be written to theFilenet.Connexact point of any object that implements theio.Writerinterface.



Because of the non-intrusive nature of the go language interface, we can implement our own objects independently, as long as they conform to the interface, andio.Writerthen we can work with themfmt.Fprintf.



The subsequent mutable parameterinterface{}is also an interface that replaces the C languagevoid*for formatting output of various types of values. (More precisely, in addition to the underlying type, the parameteramust be anStringerextension type that implements the interface).



The interface is a completely orthogonal feature that can beFprintfa ...interface{}completely stripped out from various, as well as variousw io.Writer.
The go language is the same,structsuch as the underlying type of memory layout or C language, just add amethod(in Go1.1,method valueis a normal closure function), interface andgoroutineall are without destroying the original type semantics based on the orthogonal extension (not like C + + That's a constructor, and then a destructor.



I would like to know how it is implemented in languages such as C++/c#/javafmt.Fprintf.



To use the original author of a sentence as the end: Go language Although there are shortcomings, even if the old Zhao is a cow, but this spit groove is really general !


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.