Interface is not a value type (Interface values is valueless)

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed. # # Introduction (Introduction) Recently, I've seen a lot of problems with interfaces on Slack. Most of the time, the answers are technical and focus on the details of the implementation. Implementation (detail) is helpful for debugging, but it doesn't help the design. When designing code with interfaces, behavior is the main concern. In this blog post, I want to provide a different way of thinking about interfaces, and using them for code design. I want you to stop focusing on the implementation details, but instead focus on the relationship between the interface and the specific data. # # for data oriented design I believe that writing Go code should be done with a data-oriented approach rather than object-oriented. My first rule of data-oriented is that if you don't understand the data you're dealing with, you don't understand the problem you're trying to solve. All you have to solve is essentially the problem of data conversion. There are some inputs, and then you produce the output. This is what the program is going to do. Each function you write is a small data transformation (they are just) to help you solve large data transformations. Because the problem you want to solve is the data conversion problem, you write the algorithm based on the specific data. The specific data is the physical state that you store in memory, send it over the network, write to it, and perform basic operations. [Machine sentiment] (https://mechanical-sympathy.blogspot.com/) depends on the specific data and how you allow your machine to do the data conversion. A big warning to data-oriented is about how to handle modifications. My second rule about data-oriented is that when data is modified, your problem is changed. When your problem is changed, then your algorithm will be modified accordingly. Once the data has been modified, your algorithm needs to be modified. This is the best way to ensure readability and performance. Unfortunately, most of us are taught to create more layers of abstraction to deal with change. When the design needs to be modified, I think this approach (creating more layers of abstraction) will outweigh the gains. What you need is to allow your algorithm to remain streamlined to perform the required data transformations. When data is modified, you need a way to change the algorithm without causing a cascade of changes in the entire code base. This is the time to use the interface. When you focus on the interface, you actually want to focus on the behavior. # # Details (concrete data) because each of these things is related to specific data, you should start with specific data. Start with a specific type. # # # # code Listing 1 ' go05 type file struct {string07} ' in Listing 1, line 5th, the keyword ' struct ' declares a type named file. With this specific type of declaration, youYou can create a value of this type. # # # # 2 ' go13 func main () {+ var f file ' ', thanks to the declaration of line 14th in Code Listing 2, now you have a variable of type file, in memory, named F, and reference to the specific data. This data is indexed by the variable F and can be manipulated. You can use the keyword struct again to define a second block of concrete data. # # # code Listing 3 ' go09 type pipe struct {ten name string11} ' "in Listing 3, line No. 09 declares the type ' pipe ' and has some specific data. Once again, with this type of declaration, you can create a different value in the program. # # # code Listing 4 "GO01 package main0203 Import" FMT "0405 type file struct {string07}0809 type pipe struct {ten name str Ing11}1213 func Main () {$ var f file15 var p pipe1617 fmt. Println (F, p) 18} "Now, this program has two distinct definition of specific data, and a corresponding value. In line 14th, a value of type file is created, and on line 15th, a value of type pipe is created. To complete the program, the two values are shown in the FMT package on line 17th. # # Interface value is not a value type (Interfaces is valueless) you have defined the value your program needs with the keyword ' struct '. There is another keyword that can be used to define a type. That's the keyword ' interface '. # # # code Listing 5 ' go05 type reader interface {read (b []byte) (int, error) 07} ' in line No. 05 of Code Listing 5, declares a ' interface ' type. The ' interface ' type corresponds to the ' struct ' type. The ' interface ' type can only declare a set of behavior methods. This means that the ' interface ' type does not have a specific value. # # # code Listing 6 ' Govar R reader ' It's interesting that you can declare a variable of type ' interface ', just as shown in code listing 6. It's very interesting., because if there is no specific value in ' interface ', then the variable ' r ' seems meaningless. The ' interface ' type definition and the value created are worthless! boom! The brain exploded. This is a very important concept. You must understand:-the variable ' r ' does not represent anything. -the variable ' r ' has no specific value. -Variable ' r ' has no meaning. There is an implementation detail that makes r real in the background, but it doesn't exist from our programming model. When you realize that ' interface ' is not a value type, the whole world becomes clear and understandable. # # # Code Listing 7 "go37 func retrieve (R Reader) error {data: = make ([]byte, +) 3940 len, err: = R.read (data) if err! = Nil {return err43}4445 fmt. Println (String (Data[:len])) nil47} "in code Listing 7 defines the ' Retrieve ' function, a function I call polymorphic. Before I go on, let me explain that polymorphic definitions are in order. Look at the definition of Tom Kurtz, the inventor of Basic, that will make you feel that polymorphic functions are so special. Polymorphism means that you write a particular program that behaves differently, depending on the data it is manipulating. "When I see this view, it always surprises me. It's concise, but it's a good illustration. Polymorphism is driven by specific data. It is the specific data that has the capacity to change code. As I said above, the problem you are solving is rooted in specific data. Data-oriented design is based on specific data. If you don't understand the "specific" data you're using, you don't understand the problem you're trying to solve. Tom's view has made it clear that specific data is the key to designing an abstraction that implements different behaviors (polymorphism). What a clever view. Go back to code listing 7. I will repeat it below. # # # code Listing 7-copy ' go37 func retrieve (R Reader) error {data: = make ([]byte, +) 3940 len, err: = R.read (data) If Err! = Nil {err43 return}4445 FMT. Println (String (Data[:len)) nil47} "" When you read the 37th lineWhen the retrieve function is declared, the function seems to say, pass me a value of type reader. But you know it's impossible, because there's no one value type is reader. A value of type reader does not exist at all, because reader is an interface type. We all know that interfaces are not value types. So what does the function really want to say? What it wants to say is that I will accept any specific data (any value or pointer) that implements the reader interface. However, it must implement all the methods defined by the reader interface. This is how you can achieve polymorphism in Go. Instead of binding to a single specific data, the retrieve function binds to any specific data that implements the reader interface. # # Giving data to behavior (Giving data Behavior) The next question is, how do you assign behavior to data? This is the use of the method. Method provides a mechanism for the behavior of data. Once the data has a behavioral approach, polymorphism can be achieved. Polymorphism means that you write a definite program, but his behavior may be different, and this depends on the data it operates on. "In Go, you can write functions and methods. One reason to choose a method rather than a function is that the data is required to implement a set of methods for a given interface. # # # code Listing 8 ' go05 type reader interface {read (b []byte) (int, error)}0809 type file struct {Ten name string11}1213 F UNC (file) read (b []byte) (int, error) {s: = "<rss><channel><title>going go</title></ Channel></rss> "Copy (b, s)-return Len (s), nil17}1819 type pipe struct {name String21}2223 func (pipe) re AD (b []byte) (int, error) {s: = ' {name: ' Bill ', title: "Developer"} ' copy (b, s)-return Len (s), nil27} "Please note: you may notice The receiver's method in line 13th and line 23rd, declares but does not give a variable a specific name. This is a practice, if this method does not need to use any of the receiver's data, you can not giveA specific name for the recipient. In code listing 8, in line 13th, a method is defined for the type file, and on line 23rd, a method is defined for the pipe type. Now, each type defines a method called read, which has implemented all of the methods defined by reader. With the definition of these methods, we can then say: "Type file and pipe have now implemented the reader interface." "Every word I said in that passage was important. If you have a blog post that looks at me before about value and pointer semantics, then you should know that the behavior of the data presentation is determined by the semantics you are using. I'm not going to discuss this in this post. Here is a link. [Https://www.ardanlabs.com/blog/2017/06/design-philosophy-on-data-and-semantics.html] (https://www.ardanlabs.com/blog/2017/06/design-philosophy-on-data-and-semantics.html) Once these values, values, and pointers are implemented by these methods, They can be passed to the Polymorphic function retrieve. # # # code Listing 9 ' gopackage mainimport "FMT" type Reader interface {read (b []byte) (int, error)}type file struct {name string} Func (file) read (b []byte) (int, error) {s: = "<rss><channel><title>going go</title></ Channel></rss> "Copy (b, s) return Len (s), Nil}type pipe struct {name String}func (pipe) read (b []byte) (int, err OR) {s: = ' {name: ' Bill ', title: ' Developer '} ' copy (b, s) return Len (s), Nil}func main () {f: = file{"Data.json"} p: = Pi pe{"Cfg_service"} retrieve (f) retrieve (p)}func reTrieve (r Reader) error {data: = make ([]byte,] len, err: = R.read (data) if err! = Nil {return err} FMT. Println (String (Data[:len])) return nil} ' code Listing 9 provides a complete polymorphic instance in Go and a good illustration of the idea that the interface is not a value type. The retrieve function can accept any data that implements the reader interface, any value or pointer. This is what you can see in the function calls on lines 33rd and 34th. Now you can see how high-level decoupling is achieved in Go, and this decoupling is very accurate. You now fully understand that the behavior of the data is passed as a function of the behavior. This is no longer a strange or incomprehensible way to read the code. This makes sense when you accept that the interface is not a value type. This function does not require reader values because the reader value does not exist at all. This function requires specific data that implements the method defined by the reader. # # The assignment of the interface value (Interface value Assignments) interface is not a value type of view that can be extended to an interface value assignment. Look at these types of interfaces. # # # code Listing "go05 type Reader interface {Read ()}0809 type Writer interface {ten Write ()}1213 type readwriter inte rface {Reader15 Writer16} "with these interface declarations, you can implement a specific type that implements all of these three interfaces. # # # code Listing One "go18 type system struct{19 Host string20}2122 func (*system) Read () {/* ... */}23 func (*system) Write () {/* ... */} ", you can confirm again why the interface is not a value type. # # # code Listing "go25 func Main () {$ var rw readwriter = &system{" 127.0.0.1 "}27 var r Reader = rw28 FMT. PRINTLN (rw, R)}//output&{127.0.0.1} &{127.0.0.1} "code Listing 12, the 26th line, declares a type of readwriter, the name of the RW variable, and assigned a specific piece of data. The specific data is a pointer to the system. Then, in line 27th, you define a variable of type Reader with the name R. There is an assignment operation associated with this declaration. The RW variable with the interface type Readwriter is assigned to the new variable R with the interface type Reader. This should cause us to pause for a second because the variable RW and r are of different types. We know that there is no implicit conversion between two types of different names in Go. But that's not the case with us. Because these variables are not specific value types, they are interface types. If we go back to the understanding that the interface is not a value type, then RW and r are not specific values. Therefore, the code cannot assign interface values to each other. The only thing that can be assigned is the specific data stored in the interface values. Thanks to the type declaration of the interface, the compiler can verify that the specific data inside an interface satisfies the other interface as well. Finally, we can only deal with specific data. When dealing with interface values, we can still handle only the specific data stored therein. When you pass an interface value to a FMT package for display, keep in mind that the specific data is what is displayed. Once again, he is the only real thing. # # Conclusion (conclusion) I hope this article will provide you with a way to think about interfaces and how to design code in different ways. I believe that once you get rid of the implementation details and focus on the relationship between the interface and the specific data, things will become more reasonable. Data-oriented design is the way to write better algorithms, but requires attention to decoupling behavior. The interface allows the decoupling of the behavior to be achieved by invoking the method of the specific data.

Via:https://www.ardanlabs.com/blog/2018/03/interface-values-are-valueless.html

Author: William Kennedy Translator: gogeof proofreading: polaris1119

This article by GCTT original compilation, go language Chinese network honor launches

This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove

298 Reads
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.