Deep understanding of Go interface

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

Understanding Go Interface

0. Introduction

In Golang, interface is a very important concept and feature, previously written two related articles: Golang "generic Programming", Talk about Golang interface and reflect. Then there was a topic:understanding Golang interface (Gopher China)-youtube on interface at the Gopher China 2017, the author is Francesc. So do a collation and supplement here.

1. What is Interface?

In object-oriented programming, a protocol or interface are a common means for unrelated objects) to Comm Unicate with all other.   These is definitions of methods) and values which the objects agree upon in order to co-operate. -wikipedia

This is Wikipedia's definition of protocal, and the interface class, such as Protocal, is a very helpful way to understand. Protocol, Chinese is generally called a protocol, such as a TCP protocol in a network transmission. Protocol can be thought of as an agreement between the two sides in order to communicate, interface can be analogous.

In Golang, interface is an abstract type, as opposed to an abstract type, which is a concrete type (concrete type): Int,string. The following is an example of an IO package.

// Writer is the interface that wraps the basic Write method.//// Write writes len(p) bytes from p to the underlying data stream.// It returns the number of bytes written from p (0 <= n <= len(p))// and any error encountered that caused the write to stop early.// Write must return a non-nil error if it returns n < len(p).// Write must not modify the slice data, even temporarily.//// Implementations must not retain p.type Writer interface {  Write(p []byte) (n int, err error)}// Closer is the interface that wraps the basic Close method.//// The behavior of Close after the first call is undefined.// Specific implementations may document their own behavior.type Closer interface {  Close() error}

In Golang, interface is a set of method, which is a manifestation of duck-type programming. Do not care about attributes (data), only care about behavior (methods). In particular, you can customize your own struct and provide a specific interface method to use it as a interface. Here is a typical use of interface, defining functions when the parameters are defined as interface, call the function can be very flexible.

type MyInterface interface{  Print()}func TestFunc(x MyInterface) {}type MyStruct struct {}func (me *MyStruct) Print() {}func main() {      var me Mystruct  TestFunc(me)}

2. Why Interface

The following three reasons are given in Gopher China:

    • Writing generic algorithm (generic programming)

    • Hiding implementation detail (hide concrete implementation)

    • Providing interception points (don't know how to translate)

2.1 Writing generic algorithm

Strictly speaking, generic programming is not supported in Golang. Using generic programming in high-level languages such as C + + is very simple, so generic programming has always been the most golang. But using interface we can implement generic programming, I would simply say here, specifically, I can refer to the previous article. For example, we are going to write a generic algorithm, and the formal parameter definition takes interface, taking the standard library's sort as an example.

  Package sort//A type, typically a collection, that satisfies sort. Interface can be//sorted by the routines in this package.   the methods require that the//elements of the collection being enumerated by an integer index.type Interface Interface { //Len is the number of elements in the collection.  len () int  //Less reports whether the element wit  H  //Index I should sort before the element with index J.  less (i, J int) bool  //Swap swaps the elements With indexes I and J.  swap (i, J int)}...//Sort sorts data.//It makes one call to data. Len to determine N, and O (N*log (n)) calls to//data. Less and data. Swap. The sort is isn't guaranteed to being stable.func sort (data Interface) { //Switch to heapsort if depth of 2*ceil (LG (N+1) ) is reached.  n: = data. Len ()  maxdepth: = 0  for I: = N; i > 0; I >>= 1 {   maxdepth++  }  maxdepth *= 2  quicksort (data, 0, N, maxDepth)}  

The formal parameter of the Sort function is a interface that contains three methods: Len() , Less(i,j int) Swap(i, j int) . When used regardless of the element type of the array (int, float, string ...). ), as long as we implement these three methods we can use the Sort function, thus implementing "generic programming". One thing that's more troubling is that we need to customize the array. Here is an example.

type Person struct {  Name stringAge  int}func (p Person) String() string {  return fmt.Sprintf("%s: %d", p.Name, p.Age)}// ByAge implements sort.Interface for []Person based on// the Age field.type ByAge []Person //自定义func (a ByAge) Len() int {   return len(a) }func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i]}func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }func main() {  people := []Person{   {"Bob", 31},   {"John", 42},   {"Michael", 17},   {"Jenny", 26},  }  fmt.Println(people)  sort.Sort(ByAge(people))  fmt.Println(people)}

In addition, FRANSESC in Gopher China also mentioned a more interesting thing to share with you. The following is a good guideline when we design the function.

Be conservative in what do you send, being liberal in what do you accept. -robustness Principle

Correspondence to Golang is:

Return Concrete Types, receive interfaces as parameter. -robustness Principle applied to Go

That said, but when we flip through the Golang source, some functions return value is also interface.

2.2 Hiding implement Detail

Hide the concrete implementation, this is very good understanding. For example, I design a function for you to return a interface, then you can only through the interface inside the method to do some operations, but the implementation of the internal is completely unknown. Francesc An example of the context. The context was first provided by Google and has now been incorporated into the standard library, and has been added on the basis of the original context: Cancelctx,timerctx,valuectx. Language expression sometimes slightly pale, look at the context package code it.

func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {    c := newCancelCtx(parent)    propagateCancel(parent, &c)        return &c, func() { c.cancel(true, Canceled) }}

Indicates that the upper Withcancel function returns a Context interface, but the specific implementation of this interface is the Cancelctx struct.

Newcancelctx returns an initialized Cancelctx.func Newcancelctx (parent Context) cancelctx {     return  cancelctx{       context:parent,        done:    make (Chan struct{}),    }}//A Cancelctx can be canceled. When canceled, it also cancels all children//that implement Canceler.type cancelctx struct {   context    done Chan struct{}//Closed by the first cancel call.   &NBSP;MU       sync. Mutex    children map[canceler]struct{}//set to nil by the first cancel call    err     &N Bsp;error                //set to Non-nil by the first cancel Call}func (c *canc ELCTX) Done () <-chan struct{} {   return C.done}func (c *cancelctx) ERR () error {   c.mu.lock () & nbsp  defer C.mu.unlock ()    return C.err}func (c *cancelctx) string () string {   return FMt. Sprintf ("%v.withcancel", C.context)}

Although the specific struct (which implements the context interface) returned by the previous function in the upper and lower sides is not implemented, it is completely unaware of the user.

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)    //返回 cancelCtxfunc WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) //返回 timerCtxfunc WithValue(parent Context, key, val interface{}) Context    //返回 valueCtx

2.3 Providing interception points

Francesc here interception want to express the meaning I understand should be wrapper or decorator, he gave an example as follows:

type header struct {  rt  http.RoundTripper  v   map[string]string}func (h header) RoundTrip(r *http.Request) *http.Response {  for k, v := range h.v {    r.Header.Set(k,v)  }  return h.rt.RoundTrip(r)}

With interface, we can implement the dynamic dispatch in a similar way.

3. Non-intrusive

Francesc also mentions the non-invasive nature of interface. What is an intrusive? For example, Java's interface implementation needs to display the declaration.

public class MyWriter implements io.Writer {}

This means that if you want to implement multiple interface that need to be written many times, and the package dependencies need to be managed. Dependency is evil. For example, I want to implement the IO packet inside the Reader,writer,readwriter interface, the code can be written as follows.

type MyIO struct {}func (io *MyIO) Read(p []byte) (n int, err error) {...}func (io *MyIO) Write(p []byte) (n int, err error) {...}// io packagetype Reader interface {    Read(p []byte) (n int, err error)}type Writer interface {    Write(p []byte) (n int, err error)}type ReadWriter interface {    Reader    Writer}

This kind of writing is really convenient, and it is not necessary to display the import IO package,interface the underlying implementation of the dynamic detection. This will also introduce some questions:

    1. Performance degradation. Using interface as a function parameter, runtime dynamically determines the behavior. Using a struct as a parameter, the compilation period can be determined.

    2. Do not know which interface the struct implements. This problem can be solved by using the Guru tool.

In conclusion, this non-intrusive implementation of the Golang interface is really hard to say whether it is good or bad. But it is certain that the code is easier for developers to write.

4. Interface Type Assertion

Interface like other types of conversions are generally called assertions, for instance.

func do(v interface{}) {  n := v.(int)    // might panic}

The downside of this writing is that once the assertion fails, the program will panic. One way to avoid panic is to use type assertion.

func do(v interface{}) {  n, ok := v.(int)  if !ok {  // 断言失败处理  }}

For interface operations can be handled using the reflect package, about the principle of reflect package and use can refer to my article.

5. Summary

Interface is an important feature of Golang, but this is at the cost of runtime, which means a loss of performance (about the interface of the underlying implementation and then the time to write again). Aside from the performance (in reality the program developed using Golang 99% performance is not a problem), interface for how to design our code does give a good thought.

6. Reference

1. [Golang "Generic Programming"] (http://legendtkl.com/2015/11/25/go-generic-programming/)

2. [Talk about the interface and reflect of Golang] (http://legendtkl.com/2015/11/28/go-interface-reflect/)

3. [Understanding Golang Interface (Gopher China)-youtube] (https://www.youtube.com/watch?v=F4wUrj6pmSI&t=2319s)

4. [Understanding Golang Interface (Gopher China)-slide] (https://github.com/gopherchina/conference/blob/master/2017 /1.4%20interface.presented.pdf)

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.