I have been writing Go full-time for many years. My understanding of Go has been upgraded for about three times, but each breakthrough is not brought by Go language itself, but from other languages. It can be seen that “kung fu is beyond poetry”. I want to talk to you about the key concepts behind these three upgrades: interfaces, concurrency, and reflection. None of these concepts are easy to understand, just as variables are hard to understand when you write a program.

The first was the mobile development boom. I bought a Macbook Pro, installed Xcode, and wrote Objective-C. OC author Brad Cox originally wrote Smalltalk, so he added a lot of macros on top of C to make it object-oriented. OC supports interfaces by providing protocol.

I’m really impressed with the way that the iOS framework UIKit uses delegates a lot, especially the Protocol UITableViewDelegate, which is that to perform an operation on a TableView, the user needs to provide an object that implements the interface, and that object could be self, It can also be other objects, with the emphasis on implementing the methods defined by protocol. I don’t know how many people are confused by self.delegate = self. This interface idea is found in the Go library, as well as outside, IO.Reader, IO.Writer, json.marshaler, and so on. Go is, in a sense, an interface oriented design language. If the essence of object-oriented design is interface programming, Go is it.

Two additional features of Go’s interface are the object implicit implementation interface and the empty interface as a container for all types. Implicit implementations are a bit like duck typing for dynamic languages; if an object does not implement the methods defined by the interface, it will not compile. Empty interfaces provide some generic programming capabilities and are closely related to reflection. The concept of interface is a lot of languages, in Java there is a lot of information about interface design, understanding interface, design ability will be greatly improved.

The second time I learned concurrency in Erlang was because of my complaints about concurrency in PHP. Erlang is a programming language for concurrency. It emphasizes that everything is a process, and processes are completely isolated from each other. The whole language is designed around that. Process scheduling is completely fair, not because one process takes up a lot of CPU while the other processes don’t. It is the basis of concurrency.

Alan Kay, the father of object-oriented languages and the father of Smalltalk, explained object orientation by saying: “The Big idea is messaging.” Erlang processes communicate by sending messages. Sending messages is asynchronous — The sender doesn’t have to wait for The receiver to receive The message. When a channel of Go is cached and not full, the sender is asynchronous. When a channel is not cached or full, the sender is synchronous. The sender needs to wait for the receiver to fetch the message before completing the sending. To understand messaging or channel, think of it in a larger way as a sender sending a message to a message queue and a receiver listening to a message queue.

Go’s concurrent philosophy is: “Do not communicate by sharing memory; “Go provides a concurrency mechanism similar to Erlang, but also takes care of the needs of traditional concurrent programming by providing the Sync package, the traditional locked concurrency solution. Concurrent programming can effectively improve the performance of the program, after mastering the design ability of the program also significantly improved.

The third time I was studying SICP, I thought of Hackers and Painters author Paul Graham saying in his article “The Rejection of Mediocrity” : “With the help of Lisp, our development cycle was very short. “Sometimes competitors just put out a press release announcing new features, and we can build our own version in a day or two.” Lisp macros are a form of metaprogramming, arguably the most powerful form of metaprogramming, code as data.

Just as Lisp interpreters parse code as data, Go’s reflection treats types as arguments. Go official “The Laws of Reflection” summarizes The three Laws of Reflection is The foundation, how to apply is The key. The reflection processing object is the code itself, not the direct business data, so the related processing code is quite obscure; In general, reflection code should not exist in business logic, but in libraries and frameworks. Check the frame and library, and you’ll find Reflect, which is the ugly side of Go, but it has to be faced. The upside is that Reflect is also static, unlike Lisp, which makes it impossible to read when the person is out of state. Using Go’s reflection allows you to write code that is clean to the consumer, without the type assertion that you would do with an empty interface, but with the relative run-time overhead of generating the reflection object itself. Go was designed to compile quickly, so by abandoning support for generics, Go’s authors made a trade-off.

Metaprogramming is a high-order topic, not easy to understand, but as the author of Ruby Metaprogramming says, “Where there is metaprogramming, it’s just programming.” Think of code as data. You can do more than you think. If you want to do more, Go also provides packages such as Go /types, Go/AST for parsing Go source code so you can do code generation.

As for the above three Go features, interface, concurrency and reflection, just like understanding any knowledge, I need to compare and reference with old knowledge and a lot of practice to get some experience. Go also has many excellent designs, such as Defer, Struct Embed, first-class function, etc. The design of Go is full of trade-offs. The features of the language are more focused on software engineering, and Go is also a multi-paradigm language.