Golang-interface (a basic use)

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

GitHub: https://github.com/ZhangzheBJUT/blog/blob/master/interface.md

One interface overview

If the Gorountine and channel are the cornerstone of the concurrency model that supports the go language, making the go language a beautiful landscape in today's clustered and multicore era, then the interface is the cornerstone of the entire family of Go languages, allowing the go language to reach unprecedented heights in the quest for basic programming philosophy.

The go language is a transformational faction, not an improvement, in programming philosophy. This is not because the go language has gorountine and channel, but more importantly because of the go language type system, but also because of the go language interface. The programming philosophy of the go language tends to be perfect because of its interface.

C++, the use of an Java "intrusive" interface, mainly manifested in the implementation of the class need to explicitly declare that they implement an interface. This kind of mandatory interface inheritance is a feature that has been questioned in the development of object-oriented programming.

The go language uses the "non-intrusive Interface", the interface of the Go language has its unique: as long as the public method of type T satisfies the requirements of interface I, the object of type T can be used in the place where interface I is needed, the public method of so-called type T satisfies the requirements of interface I completely. That is, type T implements a set of members as defined by interface I. the scientific name of this practice Structural Typing is called, and some people think of it as one 静态的Duck Typing .

Go is a static type. Each variable has a static type , which means that there is a known type and is determined at compile time.

type MyInt intvar i intvar j MyInt

Then the type of I is int and j is type MyInt. Even if the variables I and J have the same underlying type, they still have different static types. It is not possible to assign values to each other without conversion.

Two interface types

An important category in a type is the interface type, which expresses a fixed set of methods. an interface variable can store any actual value (non-interface), as long as the value implements the method of the interface.

type Reader interface {    Read(p []byte) (n int, err os.Error)}// Writer 是包裹了基础 Write 方法的接口。type Writer interface {    Write(p []byte) (n int, err os.Error)}var r io.Readerr = os.Stdinr = bufio.NewReader(r)r = new(bytes.Buffer)

There is one thing that must be clear, no matter what value R holds, the type of R is always IO. Reader,go is a static type, while the static type of R is IO. Reader.

an extremely important example of an interface type is the null interface:interface{}, which represents an empty collection of methods, because any value has 0 or more methods, so any value can satisfy it.

Some people say that the Go interface is dynamic type, but this is a misunderstanding. They are statically typed: the variables of the interface type always have the same static type, and this value always satisfies the null interface, but the value stored in the interface variable may be changed while it is running.

All of this must be treated with rigor, because reflection and interface are closely related.

Features of the three interfaces

The variables of the interface type store two content: The actual value assigned to the variable and the type description of the value. More precisely, the value is the actual data item that implements the interface at the bottom, and the type describes the complete type of the project. Below, for example,

var r io.Readertty, err = os.OpenFile("/dev/tty", os.O_RDWR, 0)if err != nil { return nil, err }r = tty

In the form of a pattern, R contains (value, type) pairs, such as (TTY, *os). File).

Note: Types *os.File In addition to the Read method implement other methods: Although the interface value provides only the possibility to access the Read method (that is, only the Read method can be accessed through R), the internal contains the full type information of the value (the reflection basis).

That's why you can do this:

var w io.Writerw = r.(io.Writer) //接口查询

The assertion in this assignment is a type assertion: it asserts that an entry within R also implements IO. Writer, so you can assign it to W. After the assignment, W will be included (TTY, *os. File), consistent with the saved in R.

The static type of the interface determines which method can be called through an interface variable, even if the internal actual value may have a larger set of methods.

Next, you can do this:

var empty interface{}empty = w

The null interface value E will also contain the same (TTY, *os. File). This is convenient: an empty interface can hold any value while preserving all the information about that value.

Note: There is no need for type assertion, because W definitely satisfies the null interface. In the above example, a value is changed from reader to writer, and because writer's method is not a subset of reader, the type assertion must be explicitly used.

A very important detail is the format of the inside of the interface to always (value, the actual type), without the format (value, interface type). Interface cannot hold interface values.

Four-interface Assignment

Interface assignment is divided into two scenarios in the Go language: 1. Assigning an object instance to an interface 2. Assigning an interface to another interface

    • Assigning an object instance to an interface

      Look at the following example:

        package main  import (  "fmt"  )  type LesssAdder interface {      Less(b Integer) bool      Add(b Integer)  }  type Integer int  func (a Integer) Less(b Integer) bool {      return a < b  }  func (a *Integer) Add(b Integer) {      *a += b  }  func main() {      var a Integer = 1      var b LesssAdder = &a      fmt.Println(b)      //var c LesssAdder = a      //Error:Integer does not implement LesssAdder       //(Add method has pointer receiver)  }

The go language can be based on the following functions:

Automatically generate a new less () method

Thus, the type *integer has both the less () method and the Add () method, which satisfies the Lessadder interface. And according to

func (a *Integer) Add(b Integer)】

This function cannot generate the following member methods:

func(a Integer) Add(b Integer) {    (&a).Add(b)}

Because (&a). ADD () changes only the function parameter a, which does not affect the object that is actually being manipulated externally (value passing), which does not conform to the user's expectations. So the go language does not automatically generate this function for it. Therefore, the type integer only has the less () method, the Add () method is missing, and the Lessaddr interface is not satisfied. (This can be understood: object functions of pointer types are readable and writable, and object functions of non-pointer types are read-only)

    • Assigning an interface to another interface

      In the go language, as long as two interfaces have the same method list (it doesn't matter if the order is different), then they are equivalent and can be assigned to each other. If the method list of the A interface is a subset of the method list of interface B, then interface B can be assigned to interface A, but the reverse is not possible and cannot be compiled.

Five-Interface Query

The interface query is successful and is determined at run time. Unlike the assignment of an interface, the compiler only needs to pass a static type check to determine if the assignment is feasible.

var file1  Writer = ...if file5,ok := file1.(two.IStream);ok {...}

This if statement checks whether the object instance pointed to by the File1 interface implements both. The IStream interface, if implemented, executes a specific code.

In the go language, you can ask if the object it points to is a type, for example,

var file1 Writer = ...if file6,ok := file1.(*File);ok {...}

This if statement determines whether the object instance that the File1 interface points to is the *file type, and if so, executes the specific code.

slice := make([]int, 0)slice = append(slice, 1, 2, 3)var I interface{} = sliceif res, ok := I.([]int);ok {    fmt.Println(res) //[1 2 3]}

This if statement determines whether the object that the interface I points to is []int type, if it is, the element in the output slice.

func Sort(array interface{}, traveser Traveser) error {    if array == nil {        return errors.New("nil pointer")    }    var length int //数组的长度    switch array.(type) {    case []int:        length = len(array.([]int))    case []string:        length = len(array.([]string))    case []float32:        length = len(array.([]float32))    default:        return errors.New("error type")    }    if length == 0 {        return errors.New("len is zero.")    }    traveser(array)    return nil}

by using. The (type) method can use switch to determine the type of interface storage.

Summary: This usage of the object that the query interface points to is a type that can be considered a special case of an interface query. interfaces are abstractions of the public nature of a set of types, so the difference between a query interface and a query-specific type is similar to the following two-sentence questioning:

Are you a doctor?
Is.
You're Momomo.
Is

The first sentence questioned is a group, is the query interface, and the second question has reached the specific individual, is the query concrete type.

In addition to the use of reflection can also be a type query, will be described in detail in reflection.

Reference: Http://research.swtch.com/interfaces




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.