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,下面是官方的例子:
method的receiver
有两种类型,一种是指针,一直是值:
输出:
&{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定义接口:
method继承
输出:
Hi, I am David you can call me on 13478808311
Hi, I am Messi you can call me on 13478808311
method重写
method interface重写
输出:
TypeOne
The value is: 1.000000
TypeTwo
The value is: 4.000000
TypeThree
The value is: 8.000000
曾经写了两篇博客,分别介绍了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
相关文章推荐
- Go实战--go中函数递归(recursion)的使用(The way to go)
- Go实战--go中使用cookie(The way to go)
- Go实战--go中使用base64加密(The way to go)
- Go实战--go中使用libphonenumber(The way to go)
- Go实战--go中使用google/protobuf(The way to go)
- Go实战--net/http中JSON的使用(The way to go)
- Go实战--go中使用hmac sha256(The way to go)
- Go实战--go中使用rpc(The way to go)
- 谈一谈Go的函数function的使用方法
- Go实战--go语言中执行shell脚本(The way to go)
- Go语言学习之method(The way to go)
- Go实战--实现简单的restful api(The way to go)
- Go实战--golang生成uuid(The way to go)
- Go实战--go中一些有用的代码片段(The way to go)
- Go实战--实现一个简单的tcp服务端和客户端(The way to go)
- Go实战--实现一个简单聊天室chatroom(The way to go)
- Go实战--实现一个自己的网络请求日志httplogger(The way to go)
- Go实战--go语言中执行shell脚本(The way to go)
- Go实战--go中编码转换(The way to go)
- Go实战--实现一个单向链表(The way to go)