Go_方法、方法重写、方法与函数的区别

2023-10-27

方法:

  • 方法是绑定在自定义类型上的,常用在结构体上

  • 方法方法不能直接调用,只能通过所绑定s类型的变量来调用,因为方法是和类型做关联的

  • 方法是值拷贝的传递方式,如果希望改变结构体变量的值,需要通过结构体指针实现

  • 方法名首字母大写为公共,小写为私有,与函数一致

创建格式:

func (接受者变量 接受者) 方法名 (参数列表) (返回值列表){}

调用:

对象.方法名

方法是值拷贝,在方法中修改是不会影响原数据的

type Student struct {
	name string
}

// 创建了一个StudentMethod方法,绑定了Student,可以称为Student的方法
// s是Student的变量,可以用来调用Student的成员
func (s Student) StudentMethod() {
	fmt.Println("我是Student的方法")
	fmt.Println("StudentMethod修改前:", s.name)
	s.name = "韩信"
	fmt.Println("StudentMethod修改后:", s.name)
}

func main() {
	stu := Student{"itzhuzhu"}
	stu.StudentMethod() // 调用方法
	fmt.Println("main运行修改后:", stu.name)
}

输出:

我是Student的方法
StudentMethod修改前: itzhuzhu
StudentMethod修改后: 韩信
main运行修改后: itzhuzhu

三种不同调用的方式

type Student struct {
	name string
	age  int
}

func (s *Student) StudentMethod() {
	fmt.Println(*s)
}

func main() {
	// 普通方式调用
	s := Student{name: "韩信", age: 99}
	s.StudentMethod()

	// 方法值调用
	x := s.StudentMethod
	x()

	// 方法表达式调用,要和方法对象的类型保持一致,方法对象是指针类型,这里也要加上*
	y := (*Student).StudentMethod
	//y2:=Student.StudentMethod    不可用
	//y2(&s)
	y(&s)
}

带参数和返回值的方法:返回x+y的和

type Count struct{}

func (c *Count) count(x, y int) int {
	return x + y
}

func main() {
	c := Count{}
	c.count(100, 200)
}

变量调用方法时,该变量也会作为一个参数传递到方法(如果是引用类型,则进行地址拷贝,否则为值拷贝)

type Test struct{}

func (t Test) TestMethod(x, y int) int {
	/*
		这里的变量t和main方法中的变量t,不是同一个t,因为是值拷贝,
		所以main栈调用TestMethod方法时,会将main栈的t拷贝一份到TestMethod方法中,
		如果是指针,那么拷贝的是内存地址
	*/
	fmt.Printf("TestMethod方法中的t:%p", &t)
	return x + y
}

func main() {
	t := Test{}
	fmt.Printf("main函数中的t:%p\n", &t)
	testMethod := t.TestMethod(1, 2)
	fmt.Println(testMethod)
}

输出:

main函数中的t:0x102f1bfa8
TestMethod方法中的t:0x102f1bfa83

指针类型使用方法

type Test struct {
	num int
}

func (t *Test) TestMethod(x, y int) int {
	t.num = 2
	fmt.Println("TestMethod修改为2:", t.num)
	return x + y
}

func main() {
	t := Test{}
	t.num = 1
	fmt.Println("传递TestMethod方法前:", t.num)
	
	testMethod := (&t).TestMethod(1, 2)
	fmt.Println("调用完方法后:", t.num)
	fmt.Println(&t)
	
	// 也可以简写成以下模式,因为编译器在底层做了优化,在编译时会自动加上(&)
	testMethod2 := t.TestMethod(1, 2)
	fmt.Println(testMethod)
	fmt.Println(testMethod2)
}

输出:

传递TestMethod方法前: 1
TestMethod修改为22
调用完方法后: 2
&{2}
TestMethod修改为22
3
3

方法可以作用在指定的数据类型上,所有的自定义类型都可以有方法

type integer int

func (i integer) print() {
	fmt.Println("print方法:", i)
}

func (i *integer) change() {
	fmt.Println("change方法", *i)
}
func main() {
	var i integer = 10
	i.print()
	i.change()
	fmt.Println("main方法:", i)
}

输出:

print方法: 10
change方法 10
main方法: 10

如果一个类型实现了String()方法,那么输出时会默认调用String()

type Student struct {
	name string
	age  int
}

// 改成AAA就不会默认调用了
func (stu *Student) String() string {
	return "String方法执行"
}

func main() {
	stu := Student{"不知火舞", 99}
	fmt.Println(&stu)
}

输出:

String方法执行

方法重写:

方法重写是父类中的方法与子类方法重名的问题,默认调用子类的方法,如果需要使用父类的,需要使用子类.父类.方法名调用

// 父类
type Person struct {
	name string
	age  int
}

func (p *Person) Show() {
	fmt.Println("我是Person的show方法")
}

// 子类
type Student struct {
	Person
}

func (s *Student) Show() {
	fmt.Println("我是Student的show方法")
}

func main() {
	s := Student{Person{
		name: "韩信",
		age:  99,
	}}

	s.Show() // 优先使用自己的
	//如果需要使用父类的,需要明示使用父类调用
	s.Person.Show()
}

输出:

我是Student的show方法
我是Person的show方法

方法和函数的区别:

  1. 方法有接受者,而函数无接受者
  2. 函数不可以重名,而方法可以重名(绑定不同数据类型)
  3. 调用方式不一样
函数:函数名(实参列表)
方法:变量.方法名(实参列表)
  1. 函数:
    1. 参数为值类型时不能传递指针类型,为指针类型时不能传递值类型。
    2. 方法是值类型还是指针类型,都可以使用值或指针调用

注意:判断方法是否为指针类型,不应该从调用者出发 s.Test03(),是由方法关联类型决定的(h Hero) test03()、(h *Hero) test04()

type Hero struct {
	name string
}

// 值类型函数
func test01(h Hero) {
	fmt.Println("test01:", h.name) //不知火舞
}

// 指针类型函数
func test02(h *Hero) {
	fmt.Println("test02:", h.name) //不知火舞
}

// 普通方法
func (h Hero) test03() {
	h.name = "干将莫邪"            //值拷贝,不影响主函数Name
	fmt.Println("test03:", h.name) // 干将莫邪
}

// 指针类型方法
func (h *Hero) test04() {
	h.name = "干将莫邪"            // 指针会直接修改原数据
	fmt.Println("test04:", h.name) // 干将莫邪
}

func main() {
	h := Hero{"不知火舞"}
	//test01(&h) // 无法将 '&h' (类型 *Hero) 用作类型 Hero
	test01(h)
	//test02(h) // 无法将 'h' (类型 Hero) 用作类型 *Hero
	test02(&h)

	(&h).test03() // 看似是传递指针,实际上还是传入值类型,但是本质仍然是地址拷贝,面试的时候会留坑让误以为传递的是指针,联想到是指针类型的方法
	fmt.Println("main调用test03后", h.name)

	(&h).test04()
	fmt.Println("main调用test04后", h.name) // 干将莫邪
	h.test04()                              // 等价 (&p).test04 ,
	fmt.Println("main调用test04后", h.name) // 干将莫邪
}

输出:

test01: 不知火舞
test02: 不知火舞
test03: 干将莫邪
main调用test03后 不知火舞
test04: 干将莫邪
main调用test04后 干将莫邪
test04: 干将莫邪
main调用test04后 干将莫邪

练习方法:

键盘录入数据,判断是奇数还是偶数

type TestMethod struct{}

func (t *TestMethod) JudgeNumber() {
   var num int
   fmt.Println("请输入一个整数:")
   fmt.Scan(&num)

   if num%2 == 0 {
      fmt.Println(num, "是偶数")
   } else {
      fmt.Println(num, "是奇数")
   }
}

func main() {
   t := TestMethod{}
   t.JudgeNumber()
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Go_方法、方法重写、方法与函数的区别 的相关文章

  • 在 Go 中初始化嵌入结构

    我有以下内容struct其中包含一个net http Request type MyRequest struct http Request PathParams map string string 现在我想初始化匿名内部结构http Req
  • 如何在golang中解析JSON而不需要解组两次

    我有一个 Web 套接字连接 它在 JSON 对象中发送不同类型的消息 并且我想将内容解组到一些已知的结构中 为此 我认为我应该执行以下操作 步骤 1 将 JSON 解组为通用映射 字符串 接口 步骤 2 找到我要找的钥匙 步骤 3 尝试将
  • 如何同时使用 LoadHTMLGlob 和 LoadHTMLFiles

    我想要来自不同子目录的分隔符逻辑模板templates文件夹 下面是我的templates文件夹 templates authentication login gohtml logout gohtml index gohtml profil
  • 如何仅在测试时允许一个包访问另一个包的未导出数据?

    In Go 编程语言 第 11 2 4 节 有一个外部测试访问的示例fmt isSpace 通过声明IsSpace in fmt s export test go文件 这似乎是完美的解决方案 所以这就是我所做的 a a go package
  • 如何关闭 gorm 1.20.0 中的数据库实例

    由于我没有在 Close 函数中找到 gorm 实例 任何帮助将不胜感激 dbURI fmt Sprintf user s password s dbname s port s sslmode s TimeZone s username p
  • 在 Go 中,如何将结构体转换为字节数组?

    我有一个我定义的结构实例 我想将其转换为字节数组 我尝试了 byte my struct 但这不起作用 另外 我还被指出二进制包 http golang org pkg encoding binary 但我不确定我应该使用哪个函数以及应该如
  • 如何从 JWT 令牌中提取声明

    我正在使用 dgrijalva jwt go 包 我想从令牌中提取有效负载 但找不到方法 示例 取自 https jwt io https jwt io 对于编码 eyJhbGciOiJIUZI1NiIsInR5cCI6IkpXVCJ9 e
  • RSA OAEP、Golang 加密、Java 解密 -BadPaddingException:解密错误

    我正在尝试解密使用 RSA OAEP 在 Golang 中加密的字符串 但出现 BadPaddingException 解密错误 很难弄清楚我错过了什么 这是Golang加密方法 func encryptString rootPEM io
  • select 语句是否保证通道选择的顺序?

    继从这个答案 https stackoverflow com a 25795236 274460 如果一个 goroutine 在两个通道上进行选择 是否保证通道的选择顺序与其发送的顺序相同 我对发送者是单线程的情况特别感兴趣 例如 是否保
  • 如何为所有 API 端点全局设置 http.ResponseWriter Content-Type 标头?

    我是 Go 新手 现在正在用它构建一个简单的 API package main import encoding json fmt github com gorilla mux github com gorilla handlers log
  • 如何将接口转换为接口切片?

    我的输入是interface 而且我知道它可以是任何类型的数组 我想读取我输入的元素之一 所以我尝试将我的interface 进入一个 interface 但是 go 会给我以下错误 恐慌 接口转换 interface 是 map stri
  • 在 Golang 中运行外部 python,捕获连续的 exec.Command Stdout

    所以我的 go 脚本将像这样调用外部 python cmd exec Command python game py cmd Stdout os Stdout cmd Stderr os Stderr go func err cmd Run
  • 在复杂的文件夹结构中进行测试

    我正在 golang 中构建一个设计模式存储库 为了运行所有测试 我使用这个 bash 脚本 有用 bin bash go test creational abstract factory go go test creational bui
  • Facebook服务器端登录、CORS

    我正在实现一个带有 FB 服务器端登录的网站 简化步骤如下 一个简单的按钮触发 JS 脚本 该脚本调用我的后端 APIhttps localhost fblogin function sendFbLoginData get https lo
  • 测试 gRPC 服务

    我想测试用 Go 编写的 gRPC 服务 我使用的示例是 Hello World 服务器示例grpc go 仓库 https github com grpc grpc go blob master examples helloworld g
  • 关于编写惯用的 Golang 的建议

    我正在掌握 Golang 的做事方式 首先是一些示例代码 package main import log os func logIt s string f os OpenFile errors log os O RDWR os O CREA
  • “http:多个response.WriteHeader调用”有什么不好的影响?

    尽管我发现 http 多个响应 WriteHeader 调用 例外 但我的服务器表现良好 此异常不会导致我的服务器出现恐慌或行为异常 我进行了很多搜索 但只找到了如何解决这个问题 没有文档描述异常的不良影响 有人可以帮我找出为什么 http
  • go json marshal 的默认大小写选项?

    我有以下结构要导出为 json type ExportedIncident struct Title string json title Host string json host Status string json status Dat
  • 管理多租户 ArangoDB 连接

    我使用 ArangoDB Go 使用 go driver 并且需要实现多租户 这意味着每个客户都将在单独的数据库中拥有他的数据 我想要弄清楚的是如何使这种多租户发挥作用 我知道为每个请求创建一个新的数据库连接是不可持续的 这意味着我必须维护
  • 共享 GOPATH 的良好做法是什么?

    我刚刚开始学习 Go 并阅读现有代码以了解 其他人是如何做的 在这样做时 go 工作空间 的使用 特别是当它与项目的依赖项相关时 似乎无处不在 在处理各种 Go 项目时 使用单个或多个 Go 工作区 即 GOPATH 的定义 的常见最佳实践

随机推荐

  • Mac系统下Android studio配置环境变量(ADB、JDK、GRADLE、Flutter)

    mac os 启动台 gt 终端 进入当前用户的home目录 默认 cd 若 bash profile文件不存在则创建 touch bashrc 名字可以自己定义 bash profile 打开 bash profile 文件不存在则创建则
  • 第六章 系统总线

    http eduunix ccut edu cn index2 edu C7 E5 BB AA B4 F3 D1 A7 BC C6 CB E3 BB FA BF CE B3 CC CE A2 D0 CD BC C6 CB E3 BB FA
  • 阿里P8精心整理的微服务系统架构设计手册,一睹微服务架构世界

    近几年 微服务架构在大量技术社区迅速蹿红 被认为是 IT 软件架构的未来方向 一线互联网公司由于具有大量的业务体量和业务场景 比如阿里 百度 网易 很早就开始入坑微服务架构 随着云端办公以来 发现微服务越来越重要了 Docker 容器技术和
  • MatConvNet:3.代码(一)cnn_mnist.m注释

    原文链接 https blog csdn net qq 20259459 article details 54411178 博主博客地址 http blog csdn net qq 20259459 作者邮箱 jinweizhi93 gma
  • 用函数完成两个数相加(用两个方法实现)

    用函数完成两个数相加 1 方法一 int f1 int x int y 声明函数 定义函数 int z z x y return z include
  • JAVA 敏感词过滤

    package me mymilkbottles import org apache commons lang CharUtils import java io File import java util HashMap import ja
  • 基于vue+leaflet+echart的足迹分享评论平台

    其实题目是随便取的 目的只是用来证明Vue leaflet springboot技术栈的可行性 效果 小专栏不支持上传视频 想看的话可以去我的知乎看最新的文章 那个应该可以 在这里 主要功能描述 vue leaflet结合 足迹管理 新建
  • python编程-2.编写程序,输出所有由1,2,3,4这四个数字组成的素数,并且每个数字在素数中只出现一次。

    data用于存储在一定范围内的素数 data set for n in range 1234 4321 1 if n 2 0 continue for i in range 3 int n 0 5 1 2 if n i 0 break el
  • 组合逻辑电路——编码器

    组合逻辑电路 编码器 概念 编码的概念 在数字系统中 常需要将有特定意义的信息编成二进制代码 这一过程称为编码 编码器 实现编码的数字电路被称为编码器 二进制编码器 这里我们采用与非门来设计二进制编码器 二进制编码器输出端数量不定 可以根据
  • ACM MM 2022

    有预训练 460多m 来源丨https zhuanlan zhihu com p 547671620 Bidirectional Self Training with Multiple Anisotropic Prototypes for
  • Glide使用及原理分析

    文章目录 前言 一 Glide的基本使用 二 Glide的网络请求 1 HttpURLConnection实现一个原生图片加载框架 2 Glide为什么能监听网络变化 三 Glide的生命周期 1 Fragment的生命周期 动态加载Fra
  • 解决线程安全问题的三种方法

    解决线程安全问题的三种方法 一 使用同步代码块 如 卖票案例 出现了线程安全 重复的票不能出现 步骤 成员位置建立锁对象 synchronized 锁对象 出现安全问题代码 1 锁对象 任意对象 2 必须保证多个线程使用的是同一个锁对象 3
  • pip配置问题解决-如何使用修改windows系统环境变量

    问题发现 在使用pip安装环境的时候 出现了如下的问题 解决办法 我是在windows系统环境变量上添加上python的Scripts文件夹路径 将其放到环境变量的path中去 操作如下 右键我的电脑 点开属性 在最下面的 关于 上 找到
  • 力扣:删除链表中的节点

    237 删除链表中的节点 请编写一个函数 用于 删除单链表中某个特定节点 在设计函数时需要注意 你无法访问链表的头节点 head 只能直接访问 要被删除的节点 题目数据保证需要删除的节点 不是末尾节点 示例 1 输入 head 4 5 1
  • 区块链节点和区块区别_区块链的常识之,区块链节点,是什么?

    专业科普 区块链节点 通常指的是区块链网络中的计算机 也就是说任何连接到区块链网络的计算机 包括手机 矿机等 都称为节点 比如说比特币网络 是一个公有链 用户在自己的联网电脑上运行比特币程序时 这个电脑就成为比特币区块链网络中的一个节点 是
  • 利用栈实现简单表达式求值

    简单表达式求值 关键点 首先明确要使用的数据结构 本文采用栈来实现 为了分别操作数字和运算符 采用双栈 一个数值栈和一个运算符栈 根据栈顶运算符和待入栈运算符的优先级的判断 产生中间结果 而中间结果作为最终结果的一部分需要再次入栈 栈顶运算
  • DEDECMS单独调用指定文章

    dede arclist idlist 指定ID limit 0 1 a href field title a 描述 field description dede arclist
  • js中获取body html元素

  • myBatis实现多对多操作的sql语句

    文章目录 1 角色对人 2 人对角色 3 创建数据库语句 总结 1 角色对人 实现角色对人的多对多查询 将有角色的人筛选出来 实现角色对人的多对多查询 SELECT u r id AS rid r role name r role desc
  • Go_方法、方法重写、方法与函数的区别

    方法 方法是绑定在自定义类型上的 常用在结构体上 方法方法不能直接调用 只能通过所绑定s类型的变量来调用 因为方法是和类型做关联的 方法是值拷贝的传递方式 如果希望改变结构体变量的值 需要通过结构体指针实现 方法名首字母大写为公共 小写为私