Another linguistics at Golang (9) - structures and interfaces

Basically here when the time is up on a higher level. Go the essence of the characteristics about to begin.

Structure is defined

We said that different Go pointers and C, the structure is the same as above. Go is a Shanfanjiujian language, all the puzzling properties must be removed.

Simply put, Go offer 结构体is to 使用各种数据类型定义the 不同变量组合起来of 高级数据类型. Much gossip that, look at an example:

type Rect struct {
    width float64
    length float64
}

Above, we define a rectangular structure, above all, the key is typesaid to be 定义一个新的数据类型了, and then the new data type name Rect, and finally structkeyword, indicating that the high-level data type is a structure type. In the example above, because width和length的数据类型相同, the format may be written as follows:

type Rect struct {
    width, length float64
}

Well, to use the structure dry Diansha it, calculate the area of ​​a rectangle.

package main
import (
    "fmt"
)
type Rect struct {
    width, length float64
}
func main() {
    var rectum Rectum
    rect.width = 100
    rect.length = 200
    fmt.Println(rect.width * rect.length)
}

Seen from the above examples, in fact, about the same structure type and basic data types use, the only difference is the type of structure through .access to internal members. Including 给内部成员赋值and 读取内部成员值.

In the above example, we are using the var keyword to define a variable Rect, then a member of its assignment. We can also use initialization way to assign internal members Rect variables.

package main
import (
    "fmt"
)
type Rect struct {
    width, length float64
}
func main() {
    var rect = Rect{width: 100, length: 200}
    fmt.Println(rect.width * rect.length)
}

Of course 如果你知道结构体成员定义的顺序, you can not also use key:valuethe way of assignment 直接按照结构体成员定义的顺序给它们赋值.

package main
import (
    "fmt"
)
type Rect struct {
    width, length float64
}
func main() {
    var rect = Rect { 100 , 200 }
    fmt.Println("Width:", rect.width, "* Length:",
        rect.length, "= Area:", rect.width*rect.length)
}

Structure parameter passing

We said Go函数的参数传递方式是值传递, this sentence 对结构体也是适用的

package main
import (
    "fmt"
)
type Rect struct {
    width, length float64
}
func double_area(rect Rect) float64 {
    rect.width *= 2
    rect.length *= 2
    return rect.width * rect.length
}
func main() {
    var rect = Rect { 100 , 200 }
    fmt.Println(double_area(rect))
    fmt.Println("Width:", rect.width, "Length:", rect.length)
}

The output is

80000
Width: 100 Length: 200

Although it says we will double_area function inside width and length of the structure is doubled, but still does not affect the width and length of the main function inside the rect variable.

 

Structures combining function

 

Above, we calculate the area of ​​a rectangle in the main function, but we feel that if the area of ​​a rectangle can be used as a rectangular structure "internal function" provides will be better. So that we can just say this is how much area of ​​a rectangle, rather than another to get the width and length to calculate. Now we look at the structure definition of "internal function" approach:

package main
import (
    "fmt"
)
type Rect struct {
    width, length float64
}
func (rect Rect) area() float64 {
    return rect.width * rect.length
}
func main() {
    var rect = Rect { 100 , 200 }
    fmt.Println("Width:", rect.width, "Length:", rect.length,
        "Area:", rect.area())
}

Huh? This is what the "internal method", there is no internal data types defined in the Rect ah?

Indeed, we see that, although the main function rect variable can directly call the function area () to get the rectangular area, but the area () function does not define the internal structure Rect, and this is very different from the C language . Go使用组合函数的方式来为结构体定义结构体方法. Take a closer look at the above area () function definition.

The first is the keyword funcindicates that this is a function, the second argument is 结构体类型和实例变量, the third is 函数名称the fourth is 函数返回值. Here we can see the area () function and a normal function definition 区别就在于area () function 多了一个结构体类型限定. Go this way will know this is a defined structure 方法.

It should be noted that it is 定义在结构体上面的函数(function)commonly called 方法(method).

 

Structures and pointers

We talked about before, in a pointer 指针的主要作用就是在函数内部改变传递进来变量的值. For the example above the area of a rectangle is calculated, we can modify the code as follows:

package main
import (
    "fmt"
)
type Rect struct {
    width, length float64
}
func (rect *Rect) area() float64 {
    return rect.width * rect.length
}
func main() {
    var rect = new(Rect)
    rect.width = 100
    rect.length = 200
    fmt.Println("Width:", rect.width, "Length:", rect.length,
        "Area:", rect.area())
}

In the above example, using a new function to create a structure pointer rect, rect That type is * Rect, when the structure encountered pointers, you 不需要使用*去访问结构体的成员, directly .references on it . So in the example above we use directly rect.width=100 and rect.length=200to set up a structure member value. Because this time is a rect structure pointer, we define the area () function is defined when the structure type *Rect.

In fact, in this example the calculation of the area, we do not need to change the width or length of the rectangle, the area defined function is defined when the structure type is still Rectalso possible. as follows:

package main
import (
    "fmt"
)
type Rect struct {
    width, length float64
}
func (rect Rect) area() float64 {
    return rect.width * rect.length
}
func main() {
    var rect = new(Rect)
    rect.width = 100
    rect.length = 200
    fmt.Println("Width:", rect.width, "Length:", rect.length,
        "Area:", rect.area())
}

Go here smart enough, so rect.area () is also possible.

As for 使不使用结构体指针和使不使用指针的出发点是一样的that . Another example is as follows:是否试图在函数内部改变传递进来的参数的值

package main
import (
    "fmt"
)
type Rect struct {
    width, length float64
}
func (rect *Rect) double_area() float64 {
    rect.width *= 2
    rect.length *= 2
    return rect.width * rect.length
}
func main() {
    var rect = new(Rect)
    rect.width = 100
    rect.length = 200
    fmt.Println(*rect)
    fmt.Println("Double Width:", rect.width, "Double Length:", rect.length,
        "Double Area:", rect.double_area())
    fmt.Println(*rect)
}

The output of this example is:

{100 200}
Double Width: 200 Double Length: 400 Double Area: 80000
{200 400}

Embedded type structure

We can be a 结构体内部定义另外一个结构体类型的成员. Such as the iPhone is Phone, we look at an example:
package main
import (
    "fmt"
)
type Phone struct {
    price int
    color string
}
type IPhone struct {
    phone Phone
    model string
}
func main() {
    where p iPhone
    p.phone.price = 5000
    p.phone.color = "Black"
    p.model = "iPhone 5"
    fmt.Println("I have a iPhone:")
    fmt.Println("Price:", p.phone.price)
    fmt.Println("Color:", p.phone.color)
    fmt.Println("Model:", p.model)
}

The output is

I have a iPhone:
Price: 5000
Color: Black
Model: iPhone 5

In the example above, we define a variable phone Phone IPhone inside the structure, then we can access the member data phone as normal access structure members the same. But we had a meaning “iPhone也是(is-a)Phone”, and a structure where the IPhone a phone which defines variable, gives the impression that “iPhone有一个(has-a)Phone”, very strange. Of course, Go also know this very strange way, it supports the following practices:

package main
import (
    "fmt"
)
type Phone struct {
    price int
    color string
}
type IPhone struct {
    Phone
    model string
}
func main() {
    where p iPhone
    p.price = 5000
    p.color = "Black"
    p.model = "iPhone 5"
    fmt.Println("I have a iPhone:")
    fmt.Println("Price:", p.price)
    fmt.Println("Color:", p.color)
    fmt.Println("Model:", p.model)
}

The output is

I have a iPhone:
Price: 5000
Color: Black
Model: iPhone 5

In this example, we define the structure when the IPhone, 不再定义Phone变量, 直接把结构体Phone类型定义在那里. Then IPhone can 像访问直接定义在自己结构体里面的成员一样访问Phone的成员,有点类似与继承.

In the above example, we demonstrate the members of the embedded type structure and embedded type of access, in addition, assume that the internal structure defines an A-line structure B, then A also can call all definitions in function B above.

package main
import (
    "fmt"
)
type Phone struct {
    price int
    color string
}
func (phone Phone) ringing() {
    fmt.Println("Phone is ringing...")
}
type IPhone struct {
    Phone
    model string
}
func main() {
    where p iPhone
    p.price = 5000
    p.color = "Black"
    p.model = "iPhone 5"
    fmt.Println("I have a iPhone:")
    fmt.Println("Price:", p.price)
    fmt.Println("Color:", p.color)
    fmt.Println("Model:", p.model)
    p.ringing()
}

The output is:

I have a iPhone:
Price: 5000
Color: Black
Model: iPhone 5
Phone is ringing...

interface

We look at an example, and the example of the iPhone, Nokia phones are able to call.

package main
import (
    "fmt"
)
type NokiaPhone struct {
}
func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
}
type IPhone struct {
}
func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}
func main() {
    var nokia NokiaPhone
    nokia.call()
    the iPhone IPhone
    iPhone.call()
}

We define NokiaPhone and IPhone, each with its own method call (), he said he can call. However, we think, should be able to call a cell phone, so this is not a unique feature of NokiaPhone or the IPhone. Otherwise the iPhone can not sell so expensive.

A closer look 接口的定义, first of all is the key word type, and then 接口名称, finally, keyword interfaceindicates that the type is an interface type. 在接口类型里面,我们定义了一组方法.

Go language provides an interface function, which put together all defined methods have in common, and 任何其他类型只要实现了这些方法就是实现了这个接口, 不一定非要显式地声明going to achieve what interfaces it. For example, the above phone call () method, you can define the interface Phone inside, but as long as the IPhone and NokiaPhone implements this interface is a Phone.

package main
import (
    "fmt"
)
type Phone interface {
    call()
}
type NokiaPhone struct {
}
func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
}
type IPhone struct {
}
func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}
func main() {
    var phone Phone
    phone = new(NokiaPhone)
    phone.call()
    phone = new(IPhone)
    phone.call()
}

In the example above, we define an interface Phone, the interface which has a method call (), nothing more. Then we define a variable Phone type in which the main function, and to whom were assigned to NokiaPhone and IPhone. Then calls the call () method, the output results are as follows:

I am Nokia, I can call you!
I am iPhone, I can call you!

We have said Go语言式静态类型语言,变量的类型在运行过程中不能改变before, . However, in the above example, phone seems to define the variables as Phone type, then the NokiaPhone type, finally became IPhone type, is it really?

It turned out that the language in Go inside, 一个类型A只要实现了接口X所定义的全部方法then A类型的变量also X类型的变量. In the above example, NokiaPhone IPhone are implemented and call () method Phone interface, so that they are Phone, so that a normal feel to some is not.

We add a sales method for the Phone (), again familiarize yourself with the interface usage.

package main
import (
    "fmt"
)
type Phone interface {
    call()
    sales() int
}
type NokiaPhone struct {
    price int
}
func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
}
func (nokiaPhone NokiaPhone) sales() int {
    return nokiaPhone.price
}
type IPhone struct {
    price int
}
func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}
func (iPhone IPhone) sales() int {
    return iPhone.price
}
func main() {
    var phones = [5]Phone{
        NokiaPhone{price: 350},
        IPhone{price: 5000},
        IPhone{price: 3400},
        NokiaPhone{price: 450},
        IPhone{price: 5000},
    }
    var totalSales = 0
    for _, phone := range phones {
        totalSales += phone.sales()
    }
    fmt.Println(totalSales)
}

Output:

14200

In the above example, we define an array of mobile phones, and then calculate the total price of the phone. You can see that because NokiaPhone IPhone and have achieved sales () method, so they are Phone type, but when the price is calculated, Go will know which method to achieve the object of the call.

The interface can also be used as a data member of the structure.

Suppose there are black sheep, the iPhone is not the time to buy a good several Nokia, the iPhone came out, they bought a lot of iPhone Department, dad to take a look at this kid spent a total of how much money.

package main
import (
    "fmt"
)
type Phone interface {
    sales() int
}
type NokiaPhone struct {
    price int
}
func (nokiaPhone NokiaPhone) sales() int {
    return nokiaPhone.price
}
type IPhone struct {
    price int
}
func (iPhone IPhone) sales() int {
    return iPhone.price
}
type Person struct {
    phones []Phone
    name   string
    age    int
}
func (person Person) total_cost() int {
    var sum = 0
    for _, phone := range person.phones {
        sum += phone.sales()
    }
    return sum
}
func main() {
    var bought_phones = [5]Phone{
        NokiaPhone{price: 350},
        IPhone{price: 5000},
        IPhone{price: 3400},
        NokiaPhone{price: 450},
        IPhone{price: 5000},
    }
    var person = Person{name: "Jemy", age: 25, phones: bought_phones[:]}
    fmt.Println(person.name)
    fmt.Println(person.age)
    fmt.Println(person.total_cost())
}

This example demonstrates the interface is pure as the structure of the data members. That which we define a Person structure, internal structure defines a type of mobile phone chips. In addition, we define the Person of total_cost () method used to calculate the total cost of the phone. Output:

We eat
 25 
14200

summary

Structure and implementation methods of the interface can be described Shanfanjiujian Go, in addition to many other languages ​​confusing place, and the learning curve is not large, very easy to use. However, because of the unique and rather, there may be some people think is too simple function useless, this will have their own opinion, but in a gradual course, we will gradually realize the benefits of this design brings, as well as to avoid The problem.

 

 

 

 

 

 
 
 

 

 

 

Guess you like

Origin www.cnblogs.com/tianyamoon/p/11096412.html