Reference books:
"Go Language Programming"
1. Function
Each function declaration contains a name, a list of formal parameters, an optional return list, and function body:
func name(parameter-list)(result-list){ body }
Formal parameter list: Specifies the parameter name and parameter type of another set of variables, all of which are passed from the actual parameters provided by the caller.
Return to list: Specifies the type of the function return value. When the function returns an unnamed return value or no return value, the parentheses of the return list can be ignored.
func FanOne(x float64) float64 { return (x*x) } (FanOne(3)) // 3
Here x is the formal parameter, and 3 is the actual parameter of the passed function
// Define a function that calculates the sum of two numbersfunc add(a,b int) int { return a + b } func main() { sum := add(1,2) (sum) }
2. Method
In Go, structures are like a simplified form of classes, so object-oriented programmers may ask: Where are the class methods? There is a concept in Go, which has the same name as a method and generally means the same: a Go method is a function that acts on the receiver, and the receiver is a variable of some type. Therefore, a method is a special type of function.
The receiver type can be (almost) any type, not just a structure type: any type can have methods, or even function types, which can be an alias type for int, bool, string, or arrays. But the receiver cannot be an interface type, because the interface is an abstract definition, but the method is a concrete implementation; if this is done, a compilation error will be raised:invalid receiver type…
。
The last receiver cannot be a pointer type, but it can be a pointer of any other allowed type.
A type plus its method is equivalent to an object-oriented class. An important difference is:
In Go, the code of type and the code of the method bound to it can not be placed together, they can exist in different source files, the only requirement is that they must be of the same package.
A collection of all methods on type T (or *T) is called a method set of type T (or *T).
Because methods are functions, method overloading is also not allowed, i.e., methods with only one given name for a type. But if it is based on the receiver type, there is overload: methods with the same name can exist on 2 or more different receiver types, such as doing so in the same package is allowed:
func (a *denseMatrix) Add(b Matrix) Matrix func (a *sparseMatrix) Add(b Matrix) Matrix
The alias type does not have methods that have been defined on the original type.
The general format of defining methods is as follows:
func (recv receiver_type) methodName(parameter_list) (return_value_list) { ... }
Before the method name, specify receiver in brackets after the func keyword.
ifrecv
yesreceiver
Examples ofMethod1
It is its method name, then method calls follow the traditionalSelector symbol:
recv.Method1()
。
ifrecv
is a pointer, Go will automatically dereference.
If the method does not need to use the value of recv, you can replace it with _, for example:
func (_ receiver_type) methodName (parameter_list) (return_value_list) { ... }
recv is like this or self in an object-oriented language, but there are no two keywords in Go. As you like, you can use this or self as the receiver's name. Here is an example of a simple method on a structure:
package main import "fmt" type TwoInts struct { a int b int } func main() { two1 := new(TwoInts) = 12 = 10 ("The sum is: %d\n", ()) ("Add them to the param: %d\n", (20)) two2 := TwoInts{3, 4} ("The sum is: %d\n", ()) } func (tn *TwoInts) AddThem() int { return + } func (tn *TwoInts) AddToParam(param int) int { return + + param }
Output:
The sum is: 22
Add them to the param: 42
The sum is: 7
The method can be overloaded, so here there is a little object-oriented flavor~
for example
func (a *aaa) Fan(){ } func (a *bbb)Fan(){ }
This is OK ~
3. Interface
Go is not a"Tradition"object-oriented programming language: it does not have the concept of classes and inheritance.
Interfaces are a good way to achieve polymorphism in golang. Interface types are a summary and abstraction of other types' behaviors. For a specific type, there is no need to declare which interfaces it implements, and only the methods necessary for the interface are provided.
The types introduced before are all specific types. There is also a type in the go language called interface type. An interface is an abstract type. It does not expose the layout or internal structure of the data contained, and of course there is no basic operation of those data. It only provides some methods. If you get an interface, you have no way to know what it is, but what you can know is only what it can do, or more precisely, what methods it provides.
The interface defines a set of methods (method set), but these methods do not contain (implementation) code: they are not implemented (they are abstract). The interface cannot contain variables.
Define the interface through the following format:
type Namer interface { Method1(param_list) return_type Method2(param_list) return_type ... }
The aboveNamer
is an interface type.
(According to the convention, only one method) The name of the interface is added by the method nameer
Composition of suffixes, e.g.Printer
、Reader
、Writer
、Logger
、Converter
etc. There are also some uncommon ways (as suffixeser
When it is not appropriate), for exampleRecoverable
, the interface name isable
Ending, orI
Beginning (like.NET
orJava
like that).
The interfaces in Go are very short, and they usually contain 0, up to 3 methods.
Unlike most object-oriented programming languages, an interface can have a value, an interface type variable, or an interface value in Go:var ai Namer
,ai
is a multiword data structure whose value isnil
. It is essentially a pointer, though not exactly the same thing. Pointers to interface values are illegal, not only do they work at all, but they can also cause code errors.
A type (such as a structure) can implement a method set of an interface; this implementation can be described as a collection of each specific method on a variable of the type, including a method set of the interface. ImplementedNamer
The type of the interface can be assigned to theai
(Right nowreceiver
The method table ptr pointer (method table ptr) points to the current method implementation. When another implementationNamer
The type variable of the interface is assigned toai
,receiver
The value and method table pointers will also change accordingly.
A type does not need to explicitly declare that it implements an interface: the interface is implemented implicitly. Multiple types can implement the same interface.
There can be other methods to implement the type of an interface (besides implementing the interface method). A type can implement multiple interfaces.
An interface type can contain a reference to an instance whose type implements this interface (the interface is a dynamic type).
Even if the interface is defined after the type, the two are in different packages and are compiled separately: as long as the type implements the methods in the interface, it implements this interface.
All of these features make the interface very flexible.
The first example:
package main import "fmt" type Shaper interface { Area() float32 } type Square struct { side float32 } func (sq *Square) Area() float32 { return * } func main() { sq1 := new(Square) = 5 var areaIntf Shaper areaIntf = sq1 // shorter,without separate declaration: // areaIntf := Shaper(sq1) // or even: // areaIntf := sq1 ("The square has area: %f\n", ()) }
Output:
The square has area: 25.000000
The above program defines a structureSquare
and an interfaceShaper
, there is a method for the interfaceArea()
。
existmain()
A method is createdSquare
Examples of . Defining a receiver type outside the main program isSquare
MethodArea()
, used to calculate the area of a square: structureSquare
Implemented the interfaceShaper
。
So you can put oneSquare
A variable of type is assigned to a variable of interface type:areaIntf = sq1
。
The interface variable now contains a pointerSquare
References to variables, through which they can be calledSquare
Method onArea()
. Of course, you can also directlySquare
This method is called on instances, but it is more exciting to call this method on interface instances, which makes this method more general. The interface variable contains the value of the receiver instance and a pointer to the corresponding method table.
This is the Go version of polymorphism, which is a well-known concept in object-oriented programming: selecting the right method based on the current type, or in other words: the same type seems to show different behaviors on different instances.
ifSquare
No implementationArea()
Method, the compiler will give clear error message:
cannot use sq1 (type *Square) as type Shaper in assignment: *Square does not implement Shaper (missing Area method)
ifShaper
There is another wayPerimeter()
,butSquare
It has not been implemented, even if no one is thereSquare
If this method is called on the instance, the compiler will also give the same error as above.
Expand the above example, typeRectangle
It has also been achievedShaper
interface. Next create aShaper
Array of type, iterate over each element of it and call it on itArea()
Methods to show polymorphic behavior:
package main import "fmt" type Shaper interface { Area() float32 } type Square struct { side float32 } func (sq *Square) Area() float32 { return * } type Rectangle struct { length, width float32 } func (r Rectangle) Area() float32 { return * } func main() { r := Rectangle{5, 3} // Area() of Rectangle needs a value q := &Square{5} // Area() of Square needs a pointer // shapes := []Shaper{Shaper(r), Shaper(q)} // or shorter shapes := []Shaper{r, q} ("Looping through shapes for area ...") for n, _ := range shapes { ("Shape details: ", shapes[n]) ("Area of this shape is: ", shapes[n].Area()) } }
Output:
Looping through shapes for area ... Shape details: {5 3} Area of this shape is: 15 Shape details: &{5} Area of this shape is: 25
Callingshapes[n].Area()
At this time, I only knowshapes[n]
It's oneShaper
The object, in the end, turned into aSquare
orRectangle
and exhibit corresponding behavior.
Perhaps from now on you will see how to produce cleaner, simpler and more scalable code through the interface. In 11.12.3, you will see how easy it is to add new interfaces to types in development.
Here is a more specific example: There are two typesstockPosition
andcar
They all have onegetValue()
Method, we can define an interface with this methodvaluable
. Next define a usevaluable
Functions of type as argumentsshowValue()
, all implementedvaluable
This function can be used for all interface types.
package main import "fmt" type stockPosition struct { ticker string sharePrice float32 count float32 } /* method to determine the value of a stock position */ func (s stockPosition) getValue() float32 { return * } type car struct { make string model string price float32 } //Use method to get the value of the carfunc (c car) getValue() float32 { return } /* contract that defines different things that have value */ type valuable interface { getValue() float32 } func showValue(asset valuable) { ("Value of the asset is %f\n", ()) } func main() { var o valuable = stockPosition{"GOOG", 577.20, 4} showValue(o) o = car{"BMW", "M3", 66500} showValue(o) }
Output:
Value of the asset is 2308.800049 Value of the asset is 66500.000000
The above is the detailed content of the three-function method and interface for seven introductory tutorials in Go. For more information about Go function methods and interfaces, please pay attention to my other related articles!
How to learn Go
If you are a novice, you can learn Go language like this~
Seven Introduction Go Language
Article 1:A first look at Go introduction
Article 2:Introduction to program structure & data types
Chapter 4:Concurrent programming of channels and Goroutine
Chapter 5:Operation and processing of files and packages
Article 6:Network programming
Chapter 7:GC Garbage Recycling Three-Color Mark