前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >12.Go语言-方法

12.Go语言-方法

原创
作者头像
面向加薪学习
发布2022-09-04 10:46:09
2230
发布2022-09-04 10:46:09
举报
文章被收录于专栏:面向加薪学习面向加薪学习

第 12 章 方法

方法 其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。

代码语言:go
复制
func (t Type) methodName(parameterList) returnList{
}

上面的代码片段创建了一个接收器类型为 Type 的方法 methodName

12.1 实例绑定

代码语言:go
复制
package main

import "fmt"

// Lesson 定义一个名为 Lesson 的结构体
type Lesson struct {
    Name   string
    Target string
}

// PrintInfo 定义一个与 Lesson 的绑定的方法
func (lesson Lesson) PrintInfo() {
    fmt.Println("name:", lesson.Name)
    fmt.Println("target:", lesson.Target)
}


func main() {
    l := Lesson.Lesson{
        Name: "从0到Go语言微服务架构师",
        Target: "全面掌握Go语言微服务落地,代码级一次性解决微服务和分布式系统。",
    }
    l.PrintInfo()
}

上面的程序中定义了一个与结构体 Lesson 绑定的方法 PrintInfo() ,其中 PrintInfo 是方法名, (lesson Lesson) 表示将此方法与 Lesson 的实例绑定,这里我们把 Lesson 称为方法的接收者,而 lesson 表示实例本身,相当于 Python 中的 self ,Java 中的 this

当然,你可以把上面程序的方法改成一个函数,如下:

代码语言:go
复制
package main

import "fmt"

type Lesson struct {
    Name   string
    Target string
}

func PrintInfo(lesson Lesson) {
    fmt.Println("name:", lesson.Name)
    fmt.Println("target:", lesson.Target)
}

func main() {
    lesson := Lesson{
        Name: "从0到Go语言微服务架构师",
        Target: "全面掌握Go语言微服务落地,代码级一次性解决微服务和分布式系统。",
    }
    PrintInfo(lesson)
}

运行这个程序,也同样会输出上面一样的答案,那么我们为什么还要用方法呢?因为在 Go 中,相同的名字的方法可以定义在不同的类型上,而相同名字的函数是不被允许的。如果你在上面这个程序添加一个同名函数,就会报错。但是在不同的结构体上面定义同名的方法就是可行的。

代码语言:go
复制
package main

import "fmt"

type Lesson struct {
    Name   string
    Target string
}

func (lesson Lesson) PrintInfo() {
    fmt.Println("Lesson name:", lesson.Name)
    fmt.Println("Lesson target:", lesson.Target)
}

type Author struct {
    Name string
}

func (author Author) PrintInfo() {
    fmt.Println("author name:", author.name)
}

func main() {
    lesson := Lesson{
        Name: "从0到Go语言微服务架构师",
        Target: "全面掌握Go语言微服务落地,代码级一次性解决微服务和分布式系统。",
    }
    lesson.PrintInfo()
    author := Author{"欢喜"}
    author.PrintInfo()
}

12.2 指针接收器与值接收器

值接收器和指针接收器之间的区别在于,在指针接收器的方法内部的改变对于调用者是可见的,然而值接收器的方法内部的改变对于调用者是不可见的,所以若要改变实例的属性时,必须使用指针作为方法的接收者。看看下面的例子就知道了:

代码语言:go
复制
package main

import "fmt"

// Lesson 定义一个名为 Lesson 的结构体
type Lesson struct {
    Name string
    Target  string
    SpendTime int
}

// PrintInfo 定义一个与 Lesson 的绑定的方法
func (lesson Lesson) PrintInfo() {
    fmt.Println("name:", lesson.Name)
    fmt.Println("target:", lesson.Target)
    fmt.Println("spendTime:", lesson.SpendTime)
}

func (lesson Lesson) ChangeLessonName(name string) {
    lesson.name = name
}

// AddSpendTime 定义一个与 Person 的绑定的方法,使 age 值加 n
func (lesson *Lesson) AddSpendTime(n int) {
    lesson.SpendTime = lesson.SpendTime + n
}

func main() {
    lesson := Lesson{
        Name: "从0到Go语言微服务架构师",
        Target: "全面掌握Go语言微服务落地,代码级一次性解决微服务和分布式系统。",
        PrintTimes:  1,
    }
    fmt.Println("before change")
    lesson.PrintInfo()

    fmt.Println("after change")
    lesson.AddSpendTime(2)
    lesson.ChangeLessonName("Go语言微服务架构核心22讲")
    lesson.PrintInfo()
}

在上面的程序中, AddSpendTime 使用指针接收器最终能改变实例的 SpendTime 值,然而使用值接收器的 ChangeLessonName 最终没有改变实例 Name 的值。

12.3 在方法中使用值接收器 与 在函数中使用值参数

当一个函数有一个值参数,它只能接受一个值参数。当一个方法有一个值接收器,它可以接受值接收器和指针接收器。

代码语言:go
复制
package main

import "fmt"

type Lesson struct {
    Name string
    Target  string
    PrintTimes int
}

func (lesson Lesson) PrintInfo() {
    fmt.Println(lesson.Name)
}

func PrintInfo(lesson Lesson) {
    fmt.Println(lesson.name)
}

func main() {
    lesson := Lesson{"Go语言微服务核心架构22讲"}
    PrintInfo(lesson)
    lesson.PrintInfo()

    bPtr := &lesson
    //PrintInfo(bPtr) // error
    bPtr.PrintInfo()
}

在上面的程序中,使用值参数 PrintInfo(lesson) 来调用这个函数是合法的,使用值接收器来调用 lesson.PrintInfo() 也是合法的。

然后在程序中我们创建了一个指向 Lesson 的指针 bPtr ,通过使用指针接收器来调用 bPtr.PrintInfo() 是合法的,但使用值参数调用 PrintInfo(bPtr) 是非法的。

12.4 在非结构体上的方法

不仅可以在结构体类型上定义方法,也可以在非结构体类型上定义方法,但是有一个问题。为了在一个类型上定义一个方法,方法的接收器类型定义和方法的定义应该在同一个包中。例如:

代码语言:go
复制
package main

import "fmt"

type myInt int

func (a myInt) add(b myInt) myInt {
    return a + b
}

func main() {
    var x myInt = 50
    var y myInt = 7
    fmt.Println(x.add(y))   // 57
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第 12 章 方法
    • 12.1 实例绑定
      • 12.2 指针接收器与值接收器
        • 12.3 在方法中使用值接收器 与 在函数中使用值参数
          • 12.4 在非结构体上的方法
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档