38

Golang学习笔记之方法(method)

 5 years ago
source link: https://studygolang.com/articles/16732?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

如果对与结构体还有什么疑问的可以看一下 Golang学习笔记之结构体

⽅法总是绑定对象实例,并隐式将实例作为第⼀实参 (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作为接受者时,对于外部无效。

func (e Employee) changeName(newName string) {
    e.name = newName
}
func (e *Employee) changeAge(newAge int) {
    e.age = newAge
}
    emp1 := Employee{
        name:     "张三",
        salary:   6000,
        currency: "$",
        age:      18,
        Address:  Address{"山东", "济南"},
    }
    emp1.displaySalary()

    fmt.Println("Before call changeName ", emp1.name)
    //修改名字,未发生变化因为是值传递
    emp1.changeName("zhangsan")
    fmt.Println("After call changeName ", emp1.name) //After call changeName  张三

    fmt.Println("Before change age", emp1.age)
    //利用指针来修改年龄
    emp1.changeAge(50)
    fmt.Println("After change age", emp1.age) //After change age 50

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

//Rectangle 代码规范
type Rectangle struct {
    width  float32
    height float32
}
//Circle 代码规范
type Circle struct {
    radius float32
}
func (e Employee) changeName(newName string) {
    e.name = newName
}
func (e *Employee) changeAge(newAge int) {
    e.age = newAge
}
func main() {
    //计算面积
    re := Rectangle{20, 30}
    c := Circle{40}
    //两个类型调用同名方法
    fmt.Println(re.getArea())
    fmt.Println(c.getArea())
}

三、提阶,方法也支持提阶

emp1 := Employee{
        name:     "张三",
        salary:   6000,
        currency: "$",
        age:      18,
        Address:  Address{"山东", "济南"},
    }
    //提阶
    emp1.fullAddress()         //山东 济南,提阶相当于直接访问Address里的
    emp1.Address.fullAddress() //山东 济南

四、非结构类型的方法

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

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

//非结构体方法扩展
type myInt int

func (a myInt) add(b myInt) myInt {
    return a + b
}
func main() {
    //调用扩展的方法
    num1 := myInt(5)
    num2 := myInt(10)
    sum := num1.add(num2)
    fmt.Println("Sum is", sum)

}

下面附上完整实例程序

package main

import (
    "fmt"
    "math"
)

//Employee 需要添加注释或者改成非导出变量(首字母小写)
type Employee struct {
    name     string
    currency string
    salary   int
    age      int
    Address
}

//Address 代码规范
type Address struct {
    city  string
    state string
}

//Rectangle 代码规范
type Rectangle struct {
    width  float32
    height float32
}

//Circle 代码规范
type Circle struct {
    radius float32
}

//Employee 的方法
func (e Employee) displaySalary() {
    fmt.Println(e)
}
func (e Employee) changeName(newName string) {
    e.name = newName
}
func (e *Employee) changeAge(newAge int) {
    e.age = newAge
}

//Address 的方法
func (add Address) fullAddress() {
    fmt.Println(add.city, add.state)
}

//Rectangle 的方法计算面积
func (r Rectangle) getArea() float32 {
    return r.width * r.height
}

//Circle  的方法
func (c Circle) getArea() float32 {
    return math.Pi * c.radius * c.radius
}

//非结构体方法扩展
type myInt int

func (a myInt) add(b myInt) myInt {
    return a + b
}
func main() {
    //调用方法
    emp1 := Employee{
        name:     "张三",
        salary:   6000,
        currency: "$",
        age:      18,
        Address:  Address{"山东", "济南"},
    }
    emp1.displaySalary()

    fmt.Println("Before call changeName ", emp1.name)
    //修改名字,未发生变化因为是值传递
    emp1.changeName("zhangsan")
    fmt.Println("After call changeName ", emp1.name) //After call changeName  张三

    fmt.Println("Before change age", emp1.age)
    //利用指针来修改年龄
    emp1.changeAge(50)
    fmt.Println("After change age", emp1.age) //After change age 50

    //提阶
    emp1.fullAddress()         //山东 济南,提阶相当于直接访问Address里的
    emp1.Address.fullAddress() //山东 济南

    //计算面积
    re := Rectangle{20, 30}
    c := Circle{40}
    //两个类型调用同名方法
    fmt.Println(re.getArea())
    fmt.Println(c.getArea())

    //调用扩展的方法
    num1 := myInt(5)
    num2 := myInt(10)
    sum := num1.add(num2)
    fmt.Println("Sum is", sum)

}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK