! [Avatar] (https://raw.githubusercontent.com/studygolang/gctt-images/master/interface-in-go/part1-1.jpg) interface improves the elasticity and extensibility of the Code, It is also a way to implement polymorphism in the go language. Interfaces allow for the implementation of some necessary behavior, and no longer require a specific type to be set. This behavior is defined by some method settings: ' Gotype I interface {f1 (name string) f2 (name string) (Error, float32) F3 () Int64} "does not require a specific implementation. Simply by defining a method in the type that contains the target name and the signature (input and output parameter list), it is sufficient to indicate that its implementation (satisfies) an interface: "' Gotype t Int64func (t) F1 (name string) {FMT. PRINTLN (name)}func (t) f2 (name string) (Error, float32) {return nil, 10.2}func (T) F3 () Int64 {return 10} ' type T implements the first process Interface I of the sequence segment. For example, a value of type T can be passed to any function that accepts I as a parameter ([Source code] (https://play.golang.org/p/aUyEa-HgYi)): ' Gotype I interface {M () String}type T St ruct {name String}func (T T) M () string {return T.name}func Hello (i) {fmt. Printf ("Hi, my name is%s\n", I.M ())}func main () {Hello (t{name: "Michał"})//"Hi, my name is Michał"} "in function Hello , the method invokes ' I.M () '. The process is summed up by the invocation of interface I, as long as the method from a different type is implemented by type. The prominent feature of the go language is that its ' interface ' is implicitly implemented. The programmer does not need to specify the type T implementation of interface I. This work is done by the go compiler (not requiredTo send a man to do the work of the machine). The way in which this behavior is implemented is great because the definition of interface is automatically implemented by a type that has already been written (there is no need to make any changes). The reason interface can provide resiliency is because any type can implement multiple interface ([code] (https://play.golang.org/p/cN6KrJab-l)): ' Gotype I1 interface {M1 ()}type I2 interface {M2 ()}type T struct{}func (T) M1 () {fmt. Println ("T.m1")}func (T) M2 () {fmt. Println ("t.m2")}func F1 (i I1) {i.m1 ()}func F2 (i I2) {i.m2 ()}func main () {t: = t{} f1 (t)//"T.M1" F2 (t)//"T.M2"} " ' Or the same interface can implement multiple type ([Source code] (HTTPS://PLAY.GOLANG.ORG/P/_7MKHDEILZ)): ' Gotype I interface {M ()}type T1 struct{} Func (T1) M () {fmt. Println ("T1. M ")}type T2 Struct{}func (T2) m () {FMT. Println ("T2. M ")}func f (i i) {I.M ()}func main () {f (t1{})//" T1. M "F (t2{})//" T2.M "}" > * Besides the method required by one or more interface, type is free to implement other methods *---in go, we have two concepts related to interface: 1. Interface-A set of methods required to implement such an interface via [keyword] (https://golang.org/ref/spec#Keywords) ' interface '; 2. Interface type-A variable of the interface type that can hold some values that are implemented on a particular interface. Let's discuss these topics in the next two sections. # # defines a declaration of an interface type that specifies a method that belongs to it (interface). The method is defined by its name (method name) and signature-Input and interface parameters: "' Gotype I INTERFACe {m1 () m2 (int) m3 (int) int m4 () int} "" In addition to methods, it also allows embedding other interfaces-defined or introduced in the same package-by [qualified name] (https://golang.org/ref/spec# qualifiedident). It adds all the methods from the embedded interface: ' ' goimport ' FMT ' type I interface {m1 ()}type J interface {m2 () I fmt. The method group for Stringer} ' interface J includes: * M1 () from the embedded interface i* m2 () * string () string (from the embedded interface [Stringer] (https://golang.org/pkg/fmt/#Stringer ) Order does not matter, so the method specification and the embedded interface type can be completely interleaved. > * Added an export method from an embedded interface type (beginning with an uppercase letter) and a non-export method (starting with a lowercase letter) * If I embed an interface J, and the interface J is embedded in the interface K, all the methods in K are also added to I: "' Gotype I interface {J I ( )}type J Interface {k J ()}type K interface {k ()} ' I ' method group includes ' I () ', ' J () ' and ' K () ' ([Source code] (Https://play.golang.org/p/mz_8CM MDSN)). Loop embedding interface is not allowed (i.e. a embedded b,b embedded c,c embedded a), and during the compilation phase, the interface's loop embedding problem is detected ([Source code] (Https://play.golang.org/p/CXf3-quH0A)): ' Gotype I interface {J I ()}type J interface {k J ()}type K interface {k () i} ' the compiler will present an error ' interface type loop involving I '. The interface method must have a unique name ([source code] (Https://play.golang.org/p/zt3t-GUrYU)): ' Gotype I interface {J I ()}type J Interface {J () I (int)} " Otherwise, a compile-time error will be thrown: ' Duplicate method i '. The composition of the interface can beFound in the standard library. An example of this is IO. Readwriter: ' Gotype readwriter interface {Reader Writer} ' We know how to create a new interface. Now let's learn the value of the interface type ... # # interface Type the value of the interface type I variable can maintain any value of implementation I ([Source code] (HTTPS://PLAY.GOLANG.ORG/P/ZVAQ5C97WP)): "' Gotype I interface { Method1 ()}type T struct{}func (t) method1 () {}func main () {var i = t{} fmt. Println (i)} "' Here we have a variable i from interface type I. # # # Static type VS dynamic Type the variable type is known during the compilation phase. This is specified at the time of declaration, is no longer changed, and is referred to as a static type (or simply a type). A variable of an interface type also has a static type, which is itself an interface. They also have types that can specify a value-dynamic type ([Source code] (HTTPS://PLAY.GOLANG.ORG/P/UVMQQMNSB8)): ' Gotype I interface {M ()}type T1 struct {}func (T1) M () {}type T2 struct {}func (T2) m () {}func main () {var i i = t1{} i = t2{} _ = i} ' the static type of variable i is I. This is not the same. On the other hand, the dynamic type is ... Well, it's dynamic. After the first allocation, the dynamic type of I is T1. This is not immutable, so the dynamic type of I is assigned the second time to T2. The dynamic type is not set when the value of the interface type value is nil (0 value of the interface type). # # # How do I get an interface type worth dynamic type? The package [reflect] (https://golang.org/pkg/reflect/) can be used to obtain this ([Source code] (https://play.golang.org/p/9cQ5JqSxL5)): ' Gofmt. Println (reflect. TypeOf (i). Pkgpath (), reflect. TypeOf (i). Name ()) fmt. Println (reflect. TypeOf (i). String ()) "Through the package [FMT] (https://golang.org/pkg/fmt/) and the format verb '%d ' can also do this: ' ' gofmt. Printf ("%t\n", I) "uses the package *reflect* package under hood, and even if I is nil, this method works." # # # NULL Interface value This time we will start with an example ([Source code] (Https://play.golang.org/p/kv9XUzIxBU)): ' Gotype I interface {M ()}type T struct {}func (t) M () {}func main () {var t *t if T = = nil {fmt. Println ("T is nil")} else {fmt. Println ("T is not nil")} var i i = t if i = = nil {fmt. Println ("I is nil")} else {fmt. Println ("I was not nil")} ' output: ' t is Nili was not nil ' ' for the first time, it would be a surprise. The value of the variable i, we set it to nil, but the value here is not equal to nil. In fact, the interface type value consists of two components: * Dynamic type * Dynamic value dynamic type has been discussed before ("Static type vs Dynamic type" section). The dynamic value is the specified actual value. In the discussion section after assigning ' var i = t ', the dynamic value of I is nil, but the dynamic type is \**t* after this copy, the function calls ' FMT. Printf ("%t\n", i) ' will print ' *main. T '. ' When and only if the dynamic and dynamic types are nil, the interface type value is nil. The result is that even if the interface type value contains a nil pointer, the interface value is not nil. The known error is returning uninitialized, returning the interface type from the function to the non-interface type value ([Source code] (Https://play.golang.org/p/4-M35Nc2JZ)): ' Gotype I interface {}type T struct {} Func F () I {var T *t if False {//not reachable but it actually sets value t = &t{}} return T}func main () (FMT). Printf ("f () =%v\n", f ()) fmt. PriNTF ("f () is nil:%v\n", f () = = nil) fmt. Printf ("Type of f ():%T", F ())} "' It prints out: ' ' f () = <nil>f () is Nil:falsetype of F (): *main. T ' is simply because the value of the interface type returned from the function has a dynamic type set (*main. T). It is not equal to nil. The method set of an empty interface interface does not have to contain at least one member (that is, the method set is empty). It can be completely empty ([source code] (https://play.golang.org/p/V0GEG5nuW3)): ' Gotype I interface {}type T struct {}func (t) M () {}func main () {var i = t{} _ = i} ' empty interface can automatically satisfy any type-so any type of value can be assigned to such an interface type value. The behavior of a dynamic type or a static type is applied to an empty interface, as if it were applied to a non-null interface. The significant use of an empty interface exists in the parametric variable function [FMT. PRINTLN] (https://golang.org/pkg/fmt/#Println). ---# # satisfies an interface each of the types of interfaces that implement an interface automatically satisfies this interface. We do not need to use any other keyword in these types (such as implements in Java) to indicate that the type implements the interface. It is automatically implemented by the compiler of the Go language, and here is where the language is powerful ([source code] (HTTPS://PLAY.GOLANG.ORG/P/U4R6I2X5XB)): ' Goimport ("FMT" "regexp") type I interface {Find (b []byte) []byte}func f (i) {fmt. Printf ("%s\n", I.find ([]byte ("abc")))}func main () {var re = RegExp. Mustcompile (' B ') f (re)} "Here we define one by [RegExp. REGEXP] (https://golang.org/pkg/regexp/#Regexp) type implements an interface that does not have any changes to the Regexp module built into the interface. # # Behavior Abstract Interface Type Value * * Only * * method that allows access to its own interface type. If it is a struct, array, scalar, etc., the details about the exact value are hidden ([Source code] (https://play.golang.org/p/kCjgQFCsL_)): ' Gotype I interface {M1 ()}type T int64func (T) M1 () {} Func (T) M2 () {}func main () {var i i = T (Ten) i.m1 () i.m2 ()//i.m2 undefined (Type I has no field or method M2)} "
via:https://medium.com/golangspec/interfaces-in-go-part-i-4ae53a97479c
Author: Michałłowicki Translator: cureking 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
109 Reads