go方法定义

devtools/2024/10/18 16:41:31/

方法定义

Golang 方法总是绑定对象实例,并隐式将实例作为第一实参 (receiver)。

只能为当前包内命名类型定义方法。
参数 receiver 可任意命名。如方法中未曾使用 ,可省略参数名。
参数 receiver 类型可以是 T 或 *T。基类型 T 不能是接口或指针。 
不支持方法重载,receiver 只是参数签名的组成部分。
可用实例 value 或 pointer 调用全部方法,编译器自动转换。

一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。

所有给定类型的方法属于该类型的方法集。

1.1.1. 方法定义:

func (recevier type) methodName(参数列表)(返回值列表){}参数和返回值可以省略
package maintype Test struct{}// 无参数、无返回值
func (t Test) method0() {}// 单参数、无返回值
func (t Test) method1(i int) {}// 多参数、无返回值
func (t Test) method2(x, y int) {}// 无参数、单返回值
func (t Test) method3() (i int) {return
}// 多参数、多返回值
func (t Test) method4(x, y int) (z int, err error) {return
}// 无参数、无返回值
func (t *Test) method5() {}// 单参数、无返回值
func (t *Test) method6(i int) {}// 多参数、无返回值
func (t *Test) method7(x, y int) {}// 无参数、单返回值
func (t *Test) method8() (i int) {return
}// 多参数、多返回值
func (t *Test) method9(x, y int) (z int, err error) {return
}func main() {}

下面定义一个结构体类型和该类型的一个方法:

package mainimport ("fmt"
)//结构体
type User struct {Name  stringEmail string
}//方法
func (u User) Notify() {fmt.Printf("%v : %v \n", u.Name, u.Email)
}
func main() {// 值类型调用方法u1 := User{"golang", "golang@golang.com"}u1.Notify()// 指针类型调用方法u2 := User{"go", "go@go.com"}u3 := &u2u3.Notify()
}

输出结果:

    golang : golang@golang.com go : go@go.com

解释: 首先我们定义了一个叫做 User 的结构体类型,然后定义了一个该类型的方法叫做 Notify,该方法的接受者是一个 User 类型的值。要调用 Notify 方法我们需要一个 User 类型的值或者指针。

在这个例子中当我们使用指针时,Go 调整和解引用指针使得调用可以被执行。注意,当接受者不是一个指针时,该方法操作对应接受者的值的副本(意思就是即使你使用了指针调用函数,但是函数的接受者是值类型,所以函数内部操作还是对副本的操作,而不是指针操作。

我们修改 Notify 方法,让它的接受者使用指针类型:

package mainimport ("fmt"
)//结构体
type User struct {Name  stringEmail string
}//方法
func (u *User) Notify() {fmt.Printf("%v : %v \n", u.Name, u.Email)
}
func main() {// 值类型调用方法u1 := User{"golang", "golang@golang.com"}u1.Notify()// 指针类型调用方法u2 := User{"go", "go@go.com"}u3 := &u2u3.Notify()
}

输出结果:

    golang : golang@golang.com go : go@go.com

注意:当接受者是指针时,即使用值类型调用那么函数内部也是对指针的操作。

方法不过是一种特殊的函数,只需将其还原,就知道 receiver T 和 *T 的差别。

package mainimport "fmt"type Data struct {x int
}func (self Data) ValueTest() { // func ValueTest(self Data);fmt.Printf("Value: %p\n", &self)
}func (self *Data) PointerTest() { // func PointerTest(self *Data);fmt.Printf("Pointer: %p\n", self)
}func main() {d := Data{}p := &dfmt.Printf("Data: %p\n", p)d.ValueTest()   // ValueTest(d)d.PointerTest() // PointerTest(&d)p.ValueTest()   // ValueTest(*p)p.PointerTest() // PointerTest(p)
}

输出:

    Data: 0xc42007c008Value: 0xc42007c018Pointer: 0xc42007c008Value: 0xc42007c020Pointer: 0xc42007c008

1.1.2. 普通函数与方法的区别

1.对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然。

2.对于方法(如struct的方法),接收者为值类型时,可以直接用指针类型的变量调用方法,反过来同样也可以。

package main//普通函数与方法的区别(在接收者分别为值类型和指针类型的时候)import ("fmt"
)//1.普通函数
//接收值类型参数的函数
func valueIntTest(a int) int {return a + 10
}//接收指针类型参数的函数
func pointerIntTest(a *int) int {return *a + 10
}func structTestValue() {a := 2fmt.Println("valueIntTest:", valueIntTest(a))//函数的参数为值类型,则不能直接将指针作为参数传递//fmt.Println("valueIntTest:", valueIntTest(&a))//compile error: cannot use &a (type *int) as type int in function argumentb := 5fmt.Println("pointerIntTest:", pointerIntTest(&b))//同样,当函数的参数为指针类型时,也不能直接将值类型作为参数传递//fmt.Println("pointerIntTest:", pointerIntTest(b))//compile error:cannot use b (type int) as type *int in function argument
}//2.方法
type PersonD struct {id   intname string
}//接收者为值类型
func (p PersonD) valueShowName() {fmt.Println(p.name)
}//接收者为指针类型
func (p *PersonD) pointShowName() {fmt.Println(p.name)
}func structTestFunc() {//值类型调用方法personValue := PersonD{101, "hello world"}personValue.valueShowName()personValue.pointShowName()//指针类型调用方法personPointer := &PersonD{102, "hello golang"}personPointer.valueShowName()personPointer.pointShowName()//与普通函数不同,接收者为指针类型和值类型的方法,指针类型和值类型的变量均可相互调用
}func main() {structTestValue()structTestFunc()
}

输出结果:

    valueIntTest: 12pointerIntTest: 15hello worldhello worldhello golanghello golang


http://www.ppmy.cn/devtools/41221.html

相关文章

爱喵喵宠物网站系统asp.netmvc

c#asp.net mvc爱喵喵宠物网站系统asp.netmvc 说明文档 运行前附加数据库.mdf(或sql生成数据库) 主要技术: 基于asp.net mvc架构和sql server数据库 功能模块: 首页 预约 猫生活 猫科普 参馆 个人中心 管理员后台可以对猫猫和猫…

JavaScript中对象(Object)方法详解

JavaScript中对象(Object)方法详解 1、JavaScript中对象方法总结:1、Object.getPrototypeOf(Object)2、Object.setPrototypeOf(nowObject,originalObject)3、Object.create(Object) 2、实例对象的方法:1、Object.prototype.isProt…

PHP单独项目启动演示

文章目录 phpstudy得到文件打开phpStudy.exe运行项目 Apache运行后又自动停止 phpstudy 得到文件 一般我们会得到这么一个项目文件,如果外层有“中文路径”,请剪切此内容作为项目根目录即可 打开phpStudy.exe 因为我又正常的编程环境和mysql&#x…

前端面试题大合集4----框架篇(React)

一、React 合成事件 Dom事件流分三个阶段&#xff1a;事件捕获阶段&#xff0c;目标阶段&#xff0c;事件冒泡阶段 React在事件绑定时有一套自身的机制&#xff0c;就是合成事件。如下比较直观&#xff1a; react中事件绑定&#xff1a; <div className"dome" …

在微信小程序项目中安装和使用 Vant 组件库

vant Wwapp 小程序开发组件库官网 Vant Weapp - 轻量、可靠的小程序 UI 组件库 安装 Vant 组件库 1.在微信小程序项目文件目录的空白位置右键&#xff0c;选择在外部终端窗口中打开 2在命令行输入如下命令&#xff08;在项目中创建包管理配置文件 package.json&#xff09; …

OKHTTP 3.12.0 以后版本 headers 中不可携带中文

今天遇到的报错&#xff1a; java.lang.llegalArgumentException: Unexpected char 0x957f at 0 in x-brand value: 电视堆栈 okhttp3.Headers.checkValue(Headers.java:272) okhttp3.Headers$Builder.add(Headers.java:312) okhttp3.Request$Builder.addHeader(Request.iava:…

MFC桌面应用中窗口的客户区与非客户区的

在MFC&#xff08;Microsoft Foundation Class&#xff09;中&#xff0c;窗口被分为客户区和非客户区。理解这两个概念对于设计和开发Windows应用程序至关重要。 客户区&#xff08;Client Area&#xff09;&#xff1a; 客户区是窗口中用于显示应用程序内容的区域。它是窗口…

接口自动化-requests库

requests库是用来发送请求的库&#xff0c;本篇用来讲解requests库的基本使用。 1.安装requests库 pip install requests 2.requests库底层方法的调用逻辑 &#xff08;1&#xff09;get / post / put / delete 四种方法底层调用 request方法 注意&#xff1a;data和json都…