您的位置:首页 > 编程语言 > Go语言

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

2017-06-15 14:29 886 查看
声明不止,继续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 main

import "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 main

import "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 main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Student struct {
Human //匿名字段
school string
}
type Employee struct {
Human //匿名字段
company string
}
//在human上面定义了一个method
func (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 main
import "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 main

import (
"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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: