Go language Development (v), go language-oriented interface

Source: Internet
Author: User
Tags email string

Go language Development (v), go language-oriented interface

I. Introduction of Duck Typing

1, Duck Typing introduction

For a strongly typed static language, to isolate changes through runtime polymorphism, multiple implementation classes must belong to the same type of system, and the is-a relationship must be established with the same abstract type in an inherited manner.
The duck typing is a feature-based, rather than type-based, polymorphic approach. Duck typing still cares about is-a, but is-a relationship is determined by the relative characteristics of each other.
Whether the is-a relationship is satisfied can be judged using the so-called duck test (Duck test).
"When you see a bird walking like a duck, swimming like a duck and barking like a duck, the bird can be called a duck." "

Duck test is a feature-based philosophy that provides a great flexibility for design. The dynamic object-oriented language, such as Python,ruby, complies with duck test to achieve runtime polymorphism.

2. C + + support for duck typing

Duck typing is not a patent for dynamic languages. As a strong type of static language, C + + also has strong support for duck typing features. However, C + + Duck typing feature support is not at run time, but at compile time.
C + + implements support for duck typing through generic programming. For a template class or a template function, the type it is required to instantiate must have a feature, such as a function signature, a type definition, a member variable, and so on. If the feature is not available, the compiler will error.
Therefore, the C + + template class, template function of the customer class to be instantiated the characteristics of the requirements, customer types need to implement the corresponding feature requirements, so that the implementation of the template reuse.
Duck typing types that need to be instantiated have consistent characteristics, and the role of template specificity is to allow different types to have uniform features (uniform interface), so template specificity can be used as an adapter between Duck typing and instantiated types. This template-specific approach is called extraction (Traits), where type extraction is most common.
Type extraction is first of all a non-intrusive intermediate layer. Otherwise, these characteristics must be provided by an instantiated type, which means that when an instantiated type needs to reuse multiple duck typing templates, it needs to cater to a variety of features so that they are often modified and become large and incomprehensible.

A duck typing template, such as a general-purpose algorithm, that requires instantiation types to provide some features, is an easy thing to do if a type is a class, because you can define any desired feature in a class. But if a basic type also wants to reuse this general algorithm, because the basic type cannot rely on itself to provide the characteristics required by the algorithm, it must be aided by the type extraction.

3. Go language support for duck typing

The go language is a static language, and the support for duck typing is implemented by structural typing.
Structural typing is the Go Language interface, that is, do not 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.

package mainimport "fmt"type ISayHello interface {   sayHello()}//美国人type AmericalPerson struct {}func (person AmericalPerson)sayHello(){   fmt.Println("Hello!")}//中国人type ChinesePerson struct {}func (person ChinesePerson)sayHello(){   fmt.Println("你好!")}func greet(i ISayHello){   i.sayHello()}func main() {   ameriacal := AmericalPerson{}   chinese := ChinesePerson{}   var i ISayHello   i = ameriacal   i.sayHello()   i = chinese   i.sayHello()}

Second, the definition and implementation of the interface

1, the definition of the interface

The interface of the go language is a data type, the interface defines all the common methods, any other type as long as the implementation of the interface definition of the method is to implement the interface. The definition syntax for an interface is as follows:

/* 定义接口 */type interface_name interface {   method_name1 [return_type]   method_name2 [return_type]   method_name3 [return_type]   ...   method_namen [return_type]}

2, the implementation of the interface

The implementation of the interface is implicit and does not require a display declaration to implement an interface, just a method interface to implement the interface. The implementation syntax for the interface is as follows:

/* 定义结构体 */type struct_name struct {   /* variables */}/* 实现接口方法 */func (struct_name_variable struct_name) method_name1() [return_type] {   /* 方法实现 */}...func (struct_name_variable struct_name) method_namen() [return_type] {   /* 方法实现*/}

3, the definition of interface and implementation examples

package mainimport "fmt"//接口的定义type ISayHello interface {   sayHello()}//接口的实现//美国人type AmericalPerson struct {}func (person AmericalPerson)sayHello(){   fmt.Println("Hello!")}//接口的实现//中国人type ChinesePerson struct {}func (person ChinesePerson)sayHello(){   fmt.Println("你好!")}func greet(i ISayHello){   i.sayHello()}func main() {   ameriacal := AmericalPerson{}   chinese := ChinesePerson{}   var i ISayHello   i = ameriacal   i.sayHello()   i = chinese   i.sayHello()}

Third, the value type of the interface

1, the value type of the interface

A type can implement any number of interfaces, each of which implements an empty interface interface{}. An interface is a set of method signatures, which is essentially a type.
If an interface variable is declared, the interface variable can store any object type that implements the interface.
The essence of an interface type is that if a data type implements the method set of the interface itself, the interface type variable can reference the value of that data type.
The interface type variable stores two pieces of information, one is the specific value assigned to the interface variable, and one is the descriptor of the type of the value, in the form (value, concrete type) instead of (value, interface type).

2. Null interface

Null interface type interface{} A method signature is not included, so all data types implement an empty interface.
An empty interface type can be used to store an instance of any data type.
If the parameter of a function is an empty interface type interface{}, it indicates that any type of data can be used. If a function returns an empty interface type, it indicates that the function can return any type of data.
interface{} can be used to pass a variable of any type to a function, but inside the function, the variable remains the interface{} type (the empty interface type), not the passed-in argument type.
The purpose of an abstract data type can be achieved by using an interface type as a parameter.
Defines a maxinterface interface that contains three method signatures:
Len () int: the length of the collection data structure must be returned
Get (int i) interface{}: Must return a data element in index I
Bigger (i, J int) bool: Returns the result of a numerical comparison at index I and J
The data types that satisfy the Maxinterface interface need to implement the above three methods.

Package Mainimport "FMT"//person types type person struct{name string age int}//Slice type intslice []inttype floatslice []f Loat32type personslice []person//Interface definition type Maxinterface interface {Len () int Get (i int) interface{} bigger (i,j int) bo Implementation of the Ol}//len () method func (x Intslice) len () int{return len (x)}func (x floatslice) len () int{return Len (x)}func (x personsl ICE) Len () int{return len (x)}//get (i int) method implements Func (x intslice) Get (i int) interface{}{return X[i]}func (x floatslice) Get (i int) interface{}{return X[i]}func (x personslice) Get (i int) interface{}{return X[i]}//bigger (i,j int) method implements Func ( x intslice) bigger (i,j int) bool{if x[i] > x[j]{return True}else{return False}}func (x floatslice)  Bigger (i,j int) bool{if x[i] > x[j]{return True}else {return false}}func (x personslice) bigger (i,j int) bool{If x[i].age > x[j].age{return True}else {return false}}//seek maximum function implementation Func max (data maxinterf ACE) (OK bool, max Interface{}) {if data. Len () = = 0{return False,nil} if data. Len () = = 1{return true,data. Get (1)} max = data. Get (0) M: = 0 for I:=1;i<data. Len (); i++{if data. Bigger (i,m) {max = data. Get (i) m = i} return True, Max}func main () {intslice: = Intslice{1, 2, 6, 222} floatslic E: = floatslice{1.99, 3.14, 24.8} Group: = personslice{person{name: "Jack", age:24}, Person{name: "Bob", age:23 }, Person{name: "Bauer", age:104}, Person{name: "Paul", age:44}, Person{name: "Sam", age:34}, Person{name : "Lice", age:54}, Person{name: "Karl", age:74}, Person{name: "Lee", Age:4},} _,m: = Max (Intslice) fmt. Println ("The biggest integer in Islice is:", m) _, M = Max (Floatslice) fmt. Println ("The biggest float in Fslice is:", m) _, M = Max (group) FMT. Println ("The oldest person in the group is:", M)}

3. Type Assertion

interface{} can be used to pass a variable of any type to a function, but inside the function, the variable remains the interface{} type (the empty interface type), not the passed-in argument type.
The conversion of an interface type to a normal type is called a type assertion (run-time determination).

func printArray(arr interface{}){       //arr是空接口,不是数组类型,报错     for _,v:=range arr{          fmt.Print(v," ")        }     fmt.Println()}

You can convert an interface type to a tile type by type assertion.

func printArray(arr interface{}){   //通过断言实现类型转换   a,_ := arr.([]int)   for _,v:=range a{      fmt.Println(v, " ")   }   fmt.Println()}

When using type assertions, it is a good idea to determine whether the assertion was successful.

b,ok := a.(T)if ok{...}

An assertion failure does not cause an error in the compile phase, so failure to judge the assertion result may result in an assertion that the fault is run.
The operations of different types of variables must be explicitly type-cast, and the result may overflow, resulting in an error.
Type assertions can also be judged with a switch statement.

var t interface{}t = functionOfSomeType()switch t := t.(type) {default:   fmt.Printf("unexpected type %T", t)       // %T prints whatever type t hascase bool:   fmt.Printf("boolean %t\n", t)             // t has type boolcase int:   fmt.Printf("integer %d\n", t)             // t has type intcase *bool:   fmt.Printf("pointer to boolean %t\n", *t) // t has type *boolcase *int:   fmt.Printf("pointer to integer %d\n", *t) // t has type *int}

Iv. reflection mechanism

The go language implements reflection, so-called reflection is the ability to check the state of the program at run time.
The reflect package implements run-time reflection, allowing the program to manipulate objects of any type.

1. Get value, type Object

Converts a variable into a reflect object (reflect. Type or Reflect.value)

t := reflect.TypeOf(i)    //reflect.Type对象v := reflect.ValueOf(i)   //reflect.Value对象

Call reflect. TypeOf (x), x is stored first on an empty interface and then passed as a parameter to the TYPEOF function; An empty interface is parsed inside the reflect.typeof function to receive type information.
In the same vein, reflect. A value information is received inside the valueof function.

2. Get the type of object or variable

Both the Value.Type () and the Value.kind () methods can get the type of the object or variable, and if it is a variable, the same type is obtained, and if it is a struct object, Value.Type () returns the name of the struct, Value.kind () returns " struct "; If it is a custom type, Value.Type () returns the custom type name, and Value.kind () returns the underlying storage type for the custom type. Therefore, Value.kind () can be used to determine if a variable is a struct.
Kind () describes the underlying type of the reflection object, not the static type. If a reflection contains a user-defined static type, the Kind () method returns the underlying data type, not the custom static type.

package mainimport (   "reflect"   "fmt")type Float float64type Person struct {   name string   age int}func main() {   var x1 int = 8   value1 := reflect.ValueOf(x1)   fmt.Println(value1.Type())//int   fmt.Println(value1.Kind())//int   var x Float = 3.14   value2 := reflect.ValueOf(x)   fmt.Println(value2.Type())//Float   fmt.Println(value2.Kind())//float64   person := Person{}   value3 := reflect.ValueOf(person)   fmt.Println(value3.Type())//Person   fmt.Println(value3.Kind())//struct}

3. Get the value of a variable and assign a value to a variable

The

Gets the value of the variable using value. The Interface () method, which returns the value of type Interface. Assigning a variable requires determining the type of the variable, and you can use the Value.kind () method if the type of the variable is reflect. Int, assign a value to the variable using the Value.setint () method.
If you want to modify the value of the reflection object, the value of the reflection object must be settable.
 settability (can be set) is a property of reflection value, and not all reflection values have settability properties. The Settability property indicates whether the reflection object can modify the actual value of the created reflection object, and can be set depending on the original value held by the reflection object. The
calls reflect. ValueOf (x), when X is passed as a parameter, the X,reflect is copied first. The interface value in the valueof function is a copy of x, not the x itself. If you want to modify X through reflection, you must pass an X pointer to get the reflect. The value pointer points to the object, using reflect. ValueOf (&x). Elem ().

Package Mainimport ("reflect", "FMT") type Float float64type Human struct {name string Age Uint8}func main () {V AR x1 int = 8 value1: = reflect. ValueOf (x1) fmt. Println (value1. Type ())//int FMT. Println (value1. Kind ())//int var x Float = 3.14//get reflect. The value object, property settability to false value2: = reflect. ValueOf (x) fmt. Println (value2. Type ())//float FMT. Println (value2. Kind ())//float64 if value2. Kind () ==reflect. float64{if value2. Canset () {value2. SetFloat (3.1415926)}} fmt. Println (value2)//3.14 Person: = human{"Bauer", 30}//Get reflect. The value pointer points to the object, and the property settability is true value3: = reflect. ValueOf (&person). Elem () fmt. Println (Value3. Type ())//person FMT. Println (Value3. Kind ())//struct FMT. Println (VALUE3)//{bauer} field0: = Value3. Fieldbyname ("name") if field0. Kind () = = reflect. string{if field0. Canset () {///Private member Cannot set field0. SetString ("Bob")}} FMT. Println (VALUE3)//{bauer} field1: = Value3. Fieldbyname ("Age")  If Field1. Kind () = = reflect. uint8{if field1. Canset () {///public member can set field1. Setuint}} fmt. Println (VALUE3)//{bauer 20}}

For structs, only the public member variable can be changed by reflect, and the private variable cannot change the value.

4. Get tag information for struct member variables

Since Golang variable capitalization is related to public private permissions, it is difficult for developers to define variable names according to their own wishes, so Golang provides a tag mechanism to provide a label for the variable, which can be used as an alias to give some storage structure to get the struct variable name.

type Person struct {   name string `Country:"CN"`   age uint8}bob := Person{"Bob", 30}v := reflect.ValueOf(bob)vt := v.Type()filed,_ := vt.FieldByName("name")fmt.Println(filed.Tag.Get("Country"))//CN

Five, the combination of interfaces

1. Structure embedding type

Struct types can contain anonymous or embedded fields. When you embed a type into a struct, the name of the embedded type acts as the field name for the embedded field.

package mainimport "fmt"type User struct {   Name string   EMail string}type Admin struct {   User   Level string}func (user *User)Notify() error{   fmt.Printf("User: Sending a Email to %s<%s>\n", user.Name,user.EMail)   return nil}func main() {   admin := &Admin{      User: User{         Name:  "Bauer",         EMail: "bauer@gmail.com",      },      Level: "super",   }   admin.Notify()   admin.User.Notify()}

When embedding a type, the method of the embedded type becomes the method of the outer type, but when the method of the embedded type is called, the recipient of the method is the inner type (the embedded type), not the outer type.
The name of the embedded type acts as the field name, while the embedded type exists as an internal type, and can be called using the following method:
admin.User.Notify()
The above code accesses the fields and methods of the internal type through the type name. Fields and methods of internal types are also promoted to external types, so methods can be called using the following methods:
admin.Notify()
Calling the Notify method through an external type is essentially a method of an internal type.

2, the way to improve the go language

The following rules promote the inner type method set in the Go language:
A, if S contains an anonymous field t,s and s The method set contains the method promotion for which the receiver is T.
When embedding a type, the receiver of the embedded type is a value-type method that is promoted and can be called by the value and pointer of the external type.
B, for
the method set of type S, contains the method promotion of the receiver T
When embedding a type, a method set that can be called by a pointer of an external type has only the recipient of the embedded type as the method set of the pointer type, that is, when the external type uses pointers to invoke methods of the inner type, only the set of internal type methods that the recipient is a pointer type is promoted.
C, if S contains an anonymous field
t,s and s The method set contains the method of the receiver T or T is promoted
When embedding a pointer to a type, the receiver of the embedded type is a value-type or pointer-type method that is promoted and can be called by the value of an external type or by a pointer.
D, if S contains an anonymous field t,s the method set does not contain the method promotion that the recipient is *t.
Rules derived from the three rules in the Go Language specification for method promotion. When embedding a type, the receiver of the embedded type is a pointer to a method that cannot be accessed by the value of the external type.

3. Combination of interfaces

In the go language, you can create new interfaces by combining interfaces, and the new interfaces inherit the abstract method of the combined interface by default.

  Package Mainimport "FMT" type Ireader interface {Read (file string) []byte}type Iwriter interface {Write (fi  Le string, data string)}//interface combination, by default inherits the abstract method in Ireader and Iwriter type Ireadwriter interface {Ireader Iwriter}type readwriter struct {}func (rw *readwriter) Read (file string) []byte {fmt. Println (file) return Nil}func (rw *readwriter) Write (file string, data string) {FMT. Printf ("filename:%s, contents:%s", File,data)}func main () {readwriter: = new (Readwriter) var irw ireadwriter = Readwri ter//OK IRW.   Read ("Abc.txt") Data: = "Hello world." Irw. Write ("Abc.txt", Data)}  
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.