Go实战--go中函数(function)和方法(method)的使用(The way to go)

来源:互联网 发布:mac开机客人用户 编辑:程序博客网 时间:2024/05/08 23:02

声明不止,继续go go go !!!

曾经写了两篇博客,分别介绍了golang中的函数和方法:

Go语言学习之函数(The way to go)

Go语言学习之method(The way to go)

简要回顾:
1 func进行函数声明

2 函数的左花括号也不能另起一行

3 不允许函数内嵌定义

4 支持多返回值、支持命名返回值

5 函数只能判断是否为nil

6 参数视为局部变量,因此不能声明同名变量

7 不支持默认参数,支持可变参数

8 可以在函数内定义匿名函数

9 闭包(以后会单独写一篇博客介绍golang中的闭包)

10 不支持函数重载

虽然已经介绍过了函数和方法,但是有些不踏实,总觉得没有把这事儿说透,说明白,所以今天旧事重提。

到底什么是method
我们看看官方的定义:
A method is a function with a special receiver argument。

看到了吧,是带有receiver的一个function,下面是官方的例子:

package mainimport "fmt"type rect struct {    width, height int}// This `area` method has a _receiver type_ of `*rect`.func (r *rect) area() int {    return r.width * r.height}// Methods can be defined for either pointer or value// receiver types. Here's an example of a value receiver.func (r rect) perim() int {    return 2*r.width + 2*r.height}func main() {    r := rect{width: 10, height: 5}    // Here we call the 2 methods defined for our struct.    fmt.Println("area: ", r.area())    fmt.Println("perim:", r.perim())    // Go automatically handles conversion between values    // and pointers for method calls. You may want to use    // a pointer receiver type to avoid copying on method    // calls or to allow the method to mutate the    // receiving struct.    rp := &r    fmt.Println("area: ", rp.area())    fmt.Println("perim:", rp.perim())}

method的receiver
有两种类型,一种是指针,一直是值:

package mainimport "fmt"type Mutatable struct {    a int    b int}func (m Mutatable) StayTheSame() {    m.a = 5    m.b = 7}func (m *Mutatable) Mutate() {    m.a = 5    m.b = 7}func main() {    m := &Mutatable{0, 0}    fmt.Println(m)    m.StayTheSame()    fmt.Println(m)    m.Mutate()    fmt.Println(m)}

输出:
&{0 0}
&{0 0}
&{5 7}

其实我们可以看到,receiver是指针也好,值也好,调用方法是一样的,这就是golang的牛逼之处。

那么什么时候receiver用指针呢?
1 改变receiver的值
2 struct本身非常的大,这样拷贝的代价是很昂贵的
3 如果struct的一个method中receiver为指针,那么其他的method的receiver最好也要用指针。

function和method
英文表述的更好:
method belongs to instance
function is a global function belongs to package.

method定义接口:

func (m *ProbeManager) Run(w *ProbeWorker) {} 
type Manager interface {    Run(w *ProbeWorker)}

method继承

package mainimport "fmt"type Human struct {    name string    age int    phone string}type Student struct {    Human //匿名字段    school string}type Employee struct {    Human //匿名字段    company string}//在human上面定义了一个methodfunc (h *Human) SayHi() {    fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)}func main() {    mark := Student{Human{"David", 32, "13478808311"}, "MIT"}    sam := Employee{Human{"Messi", 30, "13478808311"}, "Xueba Edu"}    mark.SayHi()    sam.SayHi()}

输出:
Hi, I am David you can call me on 13478808311
Hi, I am Messi you can call me on 13478808311

method重写

package mainimport "fmt"type Human struct {    name string    age int    phone string}type Student struct {    Human //匿名字段    school string}type Employee struct {    Human //匿名字段    company string}func (h *Human) SayHi() {    fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)}func (e *Employee) SayHi() {    fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,        e.company, e.phone) //Yes you can split into 2 lines here.}func main() {    mark := Student{Human{"Mark", 25, "1504268074"}, "MIT"}    sam := Employee{Human{"Sam", 45, "13478808311"}, "Xueba Edu"}    mark.SayHi()    sam.SayHi()}

method interface重写

package mainimport (    "fmt")type Base struct{}type Baser interface {    Get() float32}type TypeOne struct {    value float32    Base}type TypeTwo struct {    value float32    Base}type TypeThree struct {    value float32    Base}func (t *TypeOne) Get() float32 {    return t.value}func (t *TypeTwo) Get() float32 {    return t.value * t.value}func (t *TypeThree) Get() float32 {    return t.value + t.value}func main() {    base := Base{}    t1 := &TypeOne{1, base}    t2 := &TypeTwo{2, base}    t3 := &TypeThree{4, base}    bases := []Baser{Baser(t1), Baser(t2), Baser(t3)}    for s, _ := range bases {        switch bases[s].(type) {        case *TypeOne:            fmt.Println("TypeOne")        case *TypeTwo:            fmt.Println("TypeTwo")        case *TypeThree:            fmt.Println("TypeThree")        }        fmt.Printf("The value is:  %f\n", bases[s].Get())    }   }

输出:
TypeOne
The value is: 1.000000
TypeTwo
The value is: 4.000000
TypeThree
The value is: 8.000000

这里写图片描述

阅读全文
1 0
原创粉丝点击