Golang学习笔记之方法(method)

简介: 原文作者:学生黄哲链接:https://www.jianshu.com/p/6e615b08cfaf來源:简书简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。 ⽅法总是绑定对象实例,并隐式将实例作为第⼀实参 (receiver)。

法总是绑定对象实例,并隐式将实例作为第⼀实参 (receiver)。
• 只能为当前包内命名类型定义⽅法。
• 参数 receiver 可任意命名。如⽅法中未曾使⽤,可省略参数名。
• 参数 receiver 类型可以是 T 或 *T。基类型 T 不能是接⼝或指针。
• 不⽀持⽅法重载, receiver 只是参数签名的组成部分。
• 可⽤实例 value 或 pointer 调⽤全部⽅法,编译器⾃动转换。
• Go 不允许同名函数,但是同名方法可以定义在不同的类型上
• method和receiver必须在同一个包里定义
• 作为函数参数,值类型就是值类型,指针类型就是指针类型
• 方法有一个值类型和指针类型的接受者时,都可以直接调用,内部会
自动进行语法的转换。

一个方法只是一个函数,它有一个特殊的接收者(receiver)类型,该接收者放在 func 关键字和函数名之间。接收者可以是结构体类型或非结构体类型。可以在方法内部访问接收者。
一般语法为:

func (t receiver_type) methodName(parameter list) {}

一、参数 receiver 类型可以是 T 或 *T。以指针为接收者也是可以的。
两者的区别在于, 以*T为接收者时,方法内部对其的修改对于外部有效,而以 T作为接受者时,对于外部无效。

1func (e Employee) changeName(newName string) {
 2    e.name = newName
 3}
 4func (e *Employee) changeAge(newAge int) {
 5    e.age = newAge
 6}
 7    emp1 := Employee{
 8        name:     "张三",
 9        salary:   6000,
10        currency: "$",
11        age:      18,
12        Address:  Address{"山东", "济南"},
13    }
14    emp1.displaySalary()
15
16    fmt.Println("Before call changeName ", emp1.name)
17    //修改名字,未发生变化因为是值传递
18    emp1.changeName("zhangsan")
19    fmt.Println("After call changeName ", emp1.name) //After call changeName  张三
20
21    fmt.Println("Before change age", emp1.age)
22    //利用指针来修改年龄
23    emp1.changeAge(50)
24    fmt.Println("After change age", emp1.age) //After change age 50

二、Go 不允许同名函数,但是同名方法可以定义在不同的类型上

 1//Rectangle 代码规范
 2type Rectangle struct {
 3    width  float32
 4    height float32
 5}
 6//Circle 代码规范
 7type Circle struct {
 8    radius float32
 9}
10func (e Employee) changeName(newName string) {
11    e.name = newName
12}
13func (e *Employee) changeAge(newAge int) {
14    e.age = newAge
15}
16func main() {
17    //计算面积
18    re := Rectangle{20, 30}
19    c := Circle{40}
20    //两个类型调用同名方法
21    fmt.Println(re.getArea())
22    fmt.Println(c.getArea())
23}
 1emp1 := Employee{
 2        name:     "张三",
 3        salary:   6000,
 4        currency: "$",
 5        age:      18,
 6        Address:  Address{"山东", "济南"},
 7    }
 8    //提阶
 9    emp1.fullAddress()         //山东 济南,提阶相当于直接访问Address里的
10    emp1.Address.fullAddress() //山东 济南

四、非结构类型的方法
非结构体类型也可以定义方法,不过这里需要注意一点。为了定义某个类型的方法,接收者类型的定义与方法的定义必须在同一个包中。

因为必须在一个包中而int则在main包中我们没法去定义这个里为了简单直观,给int声明了别名


 1//非结构体方法扩展
 2type myInt int
 3
 4func (a myInt) add(b myInt) myInt {
 5    return a + b
 6}
 7func main() {
 8    //调用扩展的方法
 9    num1 := myInt(5)
10    num2 := myInt(10)
11    sum := num1.add(num2)
12    fmt.Println("Sum is", sum)
13
14}

下面附上完整实例程序

  1package main
  2
  3import (
  4    "fmt"
  5    "math"
  6)
  7
  8//Employee 需要添加注释或者改成非导出变量(首字母小写)
  9type Employee struct {
 10    name     string
 11    currency string
 12    salary   int
 13    age      int
 14    Address
 15}
 16
 17//Address 代码规范
 18type Address struct {
 19    city  string
 20    state string
 21}
 22
 23//Rectangle 代码规范
 24type Rectangle struct {
 25    width  float32
 26    height float32
 27}
 28
 29//Circle 代码规范
 30type Circle struct {
 31    radius float32
 32}
 33
 34//Employee 的方法
 35func (e Employee) displaySalary() {
 36    fmt.Println(e)
 37}
 38func (e Employee) changeName(newName string) {
 39    e.name = newName
 40}
 41func (e *Employee) changeAge(newAge int) {
 42    e.age = newAge
 43}
 44
 45//Address 的方法
 46func (add Address) fullAddress() {
 47    fmt.Println(add.city, add.state)
 48}
 49
 50//Rectangle 的方法计算面积
 51func (r Rectangle) getArea() float32 {
 52    return r.width * r.height
 53}
 54
 55//Circle  的方法
 56func (c Circle) getArea() float32 {
 57    return math.Pi * c.radius * c.radius
 58}
 59
 60//非结构体方法扩展
 61type myInt int
 62
 63func (a myInt) add(b myInt) myInt {
 64    return a + b
 65}
 66func main() {
 67    //调用方法
 68    emp1 := Employee{
 69        name:     "张三",
 70        salary:   6000,
 71        currency: "$",
 72        age:      18,
 73        Address:  Address{"山东", "济南"},
 74    }
 75    emp1.displaySalary()
 76
 77    fmt.Println("Before call changeName ", emp1.name)
 78    //修改名字,未发生变化因为是值传递
 79    emp1.changeName("zhangsan")
 80    fmt.Println("After call changeName ", emp1.name) //After call changeName  张三
 81
 82    fmt.Println("Before change age", emp1.age)
 83    //利用指针来修改年龄
 84    emp1.changeAge(50)
 85    fmt.Println("After change age", emp1.age) //After change age 50
 86
 87    //提阶
 88    emp1.fullAddress()         //山东 济南,提阶相当于直接访问Address里的
 89    emp1.Address.fullAddress() //山东 济南
 90
 91    //计算面积
 92    re := Rectangle{20, 30}
 93    c := Circle{40}
 94    //两个类型调用同名方法
 95    fmt.Println(re.getArea())
 96    fmt.Println(c.getArea())
 97
 98    //调用扩展的方法
 99    num1 := myInt(5)
100    num2 := myInt(10)
101    sum := num1.add(num2)
102    fmt.Println("Sum is", sum)
103
104}

原文发布时间为:2018-12-12
本文作者:Golang语言社区
本文来自云栖社区合作伙伴“ Golang语言社区”,了解相关信息可以关注“Golangweb”微信公众号

相关文章
|
3月前
|
编译器 Go
Golang底层原理剖析之method
Golang底层原理剖析之method
21 2
|
6月前
|
JSON 缓存 Go
Golang 语言 Web 框架 beego v2 之控制器方法和输入输出数据
Golang 语言 Web 框架 beego v2 之控制器方法和输入输出数据
51 0
|
6月前
|
存储 安全 Go
Golang 语言 method 接收者使用值类型和指针类型的区别
Golang 语言 method 接收者使用值类型和指针类型的区别
29 0
|
3月前
|
Go Java C++
Golang每日一练(leetDay0031) 解码方法、复原 IP 地址
Golang每日一练(leetDay0031) 解码方法、复原 IP 地址
33 0
Golang每日一练(leetDay0031) 解码方法、复原 IP 地址
|
3月前
|
编译器 Go
浅谈Golang T和*T方法集的关系
浅谈Golang T和*T方法集的关系
22 0
|
6月前
|
Cloud Native 程序员 Go
100天精通Golang(基础入门篇)——第19天:深入剖析Go语言中方法(Method)的妙用与实践
100天精通Golang(基础入门篇)——第19天:深入剖析Go语言中方法(Method)的妙用与实践
20 0
|
10月前
|
编译器 Linux Go
Golang减小体积包的方法和c语言调用go封装的动态库步骤
Golang减小体积包的方法和c语言调用go封装的动态库步骤
|
10月前
|
运维 NoSQL 编译器
学习golang(8) 初探:方法
学习golang(8) 初探:方法
63 0
|
12月前
|
Go 数据库
[Golang] gorm从版本1升到版本2,数据库close()方法被弃用,应该怎样去关闭数据库?
[Golang] gorm从版本1升到版本2,数据库close()方法被弃用,应该怎样去关闭数据库?
|
12月前
|
关系型数据库 MySQL Go
[Golang]存在调用同一个包内某个结构体的方法出错?可能是未初始化结构体
[Golang]存在调用同一个包内某个结构体的方法出错?可能是未初始化结构体