当前位置: 首页 > news >正文

Go基础编程 - 16 - 方法

方法

  • 概述
    • 1. 方法定义
    • 2. 值方法、指针方法
    • 3. 方法集合
  • 匿名字段
  • 表达式
  • 自定义 error


上一篇:延迟调用(defer)


概述

1. 方法定义

 func (receiver T) 方法名(参数列表) (返回值列表){}receiver:接收者参数名T:方法所属类型

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

1. 只能为当前包内(local)命名类型定义方法。
2. 参数 receiver 可以任意命名;若方法中未使用,可省略参数名。
3. 参数 receiver 类型可以是 T(值方法)或 *T(指针方法);基类型 T 不能是接口或指针。
4. 不支持方法重载,receiver 只是参数签名的组成部分。
5. 可用实例 value(值)或 pointer(指针)调用全部方法,编译器自动转换。
package mainimport "fmt"type Person struct {name string
}// 定义指针方法(*T)
func (p *Person) SetName(name string) {p.name = name
}// 定义值方法(T)
func (p Person) GetName() string {return p.name
}func (p *Person) String() string {return fmt.Sprintf("Person: %s", p.name)
}// 1.只能为当前包内命名类型定义方法
// 报错:cannot define new methods on non-local type float64
func (f float64) Add(i, j float64) float64 {return i + j
}type Iter interface{}
// 3.receiver 类型不能是 poiter 或 interface
// 报错 invalid receiver type iter (pointer or interface type)
func (Iter) SayType() {}func main() {p := Person{}   // 值类型(调用类型方法前,需要定义一个类型的值或指针)p.SetName("国庆") // 值类型调用指针方法fmt.Println(p.name)p2 := &p // 指针类型p.name = "国强"fmt.Println(p2.GetName()) // 指针类型调用值方法
}

2. 值方法、指针方法

  • 值方法 (接收者 receiver 是一个值,而非指针)

    该方法操作对应 receiver 的值的副本,即时使用了指针调用方法,但方法的接受者是值类型,所以方法内部操作还是对副本的操作,而不是指针操作

    package mainimport ("fmt"
    )type Person struct {name string
    }// 指针方法
    func (p *Person) SetName(name string) {fmt.Printf("指针 - addr: %p, %T\n", p, p)p.name = name
    }// 值方法
    func (p Person) SetNameByValue(name string) {fmt.Printf("值: %p, %T \n", &p, p)p.name = name
    }func main() {p := &Person{"中华"}		// 指针值fmt.Printf("P addr: %p, \n\n", p)  p.SetNameByValue("华夏")   // 调用值方法// p.name = 中华,并未改变,说明 p.SetNameByValue 复制了 p 的副本进行操作。fmt.Printf("name = %s\n\n", p.name)p.SetName("国庆")fmt.Printf("name = %s\n", p.name)   //  name = 国庆
    } 
    

    以上代码输出如下,可以看出:

    • p.SetName(指针方法)中 p 的地址和 main 中 p 的地址相同,为同一变量,且该方法给 p.name 重新赋值后,main 中 p.name 跟着改变。
    • p.SetNameByValue(值方法)中 p 的地址和 main 中 p 的地址不同,且调用该方法给 p.name 重新赋值后,main 中 p.name 并未改变。
    P addr: 0xc000024070,值: 0xc000024080, test.Person
    name = 中华指针 - addr: 0xc000024070, *test.Person
    name = 国庆
    
  • 指针方法(接收者 receiver 是一个指针)

    与值方法相反,当接受者是指针时,即使用值类型调用那么方法内部也是对指针的操作。

    func main() {p := Person{"中华"}		// 值类型fmt.Printf("P addr: %p, \n\n", p)  p.SetNameByValue("华夏")fmt.Printf("name = %s\n\n", p.name) // name = 中华p.SetName("国庆")// 即时 p 为值类型,调用指针类型时,指针方法内部也是对指针操作。fmt.Printf("name = %s\n", p.name)   //  name = 国庆
    } 
    
  • 方法与函数

    • 方法可以看做一种特殊(特定类型变量)的函数。

      文章开头讲过,方法总是绑定对象实例,并隐式地将实例作为第一实参 receiver。

      func (p *Person) SetName(name string) {}
      等同于
      func SetName(p *Person, name string) { }

    • 方法与函数的区别

      • 函数不属于任何类型,而方法属于特定的类型变量(receiver)的函数。
      • 接收者 receiver 无论是值类型或指针类型,都可以调用全部方法。但函数中,参数类型为值类型,则只能将值类型作为参数传递;参数类型为指针,则只能将指针类型作为参数传递。
    type Person struct {name string
    }// 指针方法
    func (p *Person) SetName(name string) {p.name = name
    }
    // 该函数与方法 p.SetName 相同 
    func SetName(p *Person, name string) {p.name = name
    }// 值方法
    func (p Person) GetName() {return p.name
    }
    // 该函数与方法 p.GetName 相同
    func GetName(p Person) string {return p.name
    }func main() {p := Person{}// 接收者 p 为值类型,可以调用指针类型方法。反之亦然。p.SetName("中国") fmt.Println(p.GetName())// 函数中,参数为指针类型,只能以指针类型作为参数,反之同理。SetName(&p, "华夏") fmt.Println(p.GetName())fmt.Println(p.GetName(), GetName(p))
    }
    

3. 方法集合

每个类型都有与之关联的方法集,这会影响到接口实现规则。
  • 一个类型的值类型的方法集合中仅包含它的所有值方法:类型 T 方法集包含全部 receiver T 方法
  • 一个类型的指针类型的方法集合囊括了所有值方法和所有指针方法:类型 *T 方法集包含全部 receiver T + *T 方法
func main() {p := Person{} // 值类型m := reflect.TypeOf(p)for i := 0; i < m.NumMethod(); i++ {method := m.Method(i)fmt.Println("Value Method:", method.Name, method.Type)}p2 := &Person{} // 指针类型m = reflect.TypeOf(p2)for i := 0; i < m.NumMethod(); i++ {method := m.Method(i)fmt.Println("Pointer Method:", method.Name, method.Type)}
}

输出:

Value Method: GetName func(test.Person) string
Pointer Method: GetName func(*test.Person) string
Pointer Method: SetName func(*test.Person, string)
Pointer Method: String func(*test.Person) string

匿名字段

参考结构体章节:8.结构体匿名字段

Golang 中,类型的成员字段在声明时没有字段名而只有类型,那么它就是一个嵌入字段,也可以被称为匿名字段。

  • 匿名字段默认采用类型作为字段名,要求字段名称必须唯一,且一个类型中同种类型的匿名字段只能有一个。

  • 任何类型都可以作为匿名字段。

  • 匿名结构体成员可直接访问;当多个匿名结构体内存在相同字段时,为了避免歧义需要指定具体的内嵌结构体的字段。

  • 推荐使用匿名方式嵌套结构体。

  • 通过匿名字段可以实现继承,实现“override”。

  • 不可递归循环嵌套(你中有我,我中有你)。

表达式

package mainimport "fmt"type Person struct {name string
}func (p *Person) SetName(name string) {p.name = name
}func (p Person) SetNameByValue(name string) {p.name = name
}func (p Person) GetName() string {return p.name
}func main() {p := Person{"Tom"}fmt.Println(p.GetName()) // 直接调用mVal := p.GetName         // 隐式传递,此时复制了pmExp := (*Person).GetName // 显式传递p.SetName("Jerry")fmt.Println(mVal(), mExp(&p), p.GetName()) // Tom Jerry JerrymExp2 := (*Person).SetNameByValue // 值方法,此时依然会复制 pmExp2(&p, "Lucy")fmt.Println(mExp(&p), p.GetName()) // Jerry JerrymExp3 := (*Person).SetNamemExp3(&p, "Lucy")fmt.Println(mExp(&p), p.GetName()) // Lucy Lucy
}

自定义 error

package mainimport ("fmt""os""time"
)type CustomError struct {path       stringop         stringcreateTime stringmessage    string
}func (e *CustomError) Error() string {return fmt.Sprintf("%s %s %s: %s", e.createTime, e.op, e.path, e.message)
}func newError(path, op, msg string) *CustomError {return &CustomError{path:       path,op:         op,createTime: time.Now().Format("2006-01-02 15:04:05"),message:    msg,}
}func Open(fname string) (err error) {f, err := os.Open(fname)if err != nil {err = newError(fname, "open", err.Error())return}defer func() {if f.Close() != nil {err = newError(fname, "close", err.Error())}}()return nil
}func main() {err := Open("./test/test.txt")fmt.Println(err)
}

相关文章:

Go基础编程 - 16 - 方法

方法 概述1. 方法定义2. 值方法、指针方法3. 方法集合 匿名字段表达式自定义 error 上一篇&#xff1a;延迟调用&#xff08;defer&#xff09; 概述 1. 方法定义 func (receiver T) 方法名(参数列表) (返回值列表)&#xff5b;&#xff5d;receiver&#xff1a;接收者参数名T…...

接口报错500InvalidPropertyException: Invalid property ‘xxx[256]‘,@InitBinder的使用

org.springframework.beans.InvalidPropertyException: Invalid property ‘xxx[256]’ of bean class [com.xxl.MailHead]: Invalid list index in property path ‘xxx[256]’; nested exception is java.lang.IndexOutOfBoundsException: Index: 256, Size: 256 从报错可以…...

Web 3.0 介绍

Web 3.0 是互联网的下一代发展阶段&#xff0c;通常被称为去中心化的网络。它与目前的 Web 2.0&#xff08;以社交媒体、云计算和中心化平台为主导&#xff09;不同&#xff0c;强调用户对数据和内容的更多掌控&#xff0c;依靠区块链、加密货币、去中心化应用&#xff08;DApp…...

一起搭WPF界面之界面切换绑定

一起搭WPF界面之界面切换绑定 前言界面填充总结 前言 在主界面中定义Grid网格&#xff0c;界面网格化后&#xff0c;可以模块化搭建界面进行填充。 界面填充 总结 提示&#xff1a;这里对文章进行总结&#xff1a; 例如&#xff1a;以上就是今天要讲的内容&#xff0c;本文仅…...

css 数字比汉字要靠上

这个问题通常是由于数字字体的下排的问题造成的&#xff0c;也就是数字的底部边缘位置比汉字的顶部边缘位置更靠下。为了解决这个问题&#xff0c;可以尝试以下几种方法&#xff1a; 使用CSS的vertical-align属性来调整对齐方式。例如&#xff0c;可以将数字的对齐方式设置为to…...

sentinel原理源码分析系列(三)-启动和初始化

本文是sentinel原理源码分析系列第三篇&#xff0c;分析sentinel启动和初始化 启动/初始化 sentinel初始化分两块&#xff0c;静态初始和适配器(包括aop) 静态初始 1. Root EntranceNode 如果我们用一栋楼类比资源调用&#xff0c;root EntranceNode好比一栋楼的大门&…...

计算机网络(九) —— Tcp协议详解

目录 一&#xff0c;关于Tcp协议 二&#xff0c;Tcp报头字段解析 2.0 协议字段图示 2.1 两个老问题 2.2 16位窗口大小 2.3 32位序号和确认序号 2.4 6个标记位 三&#xff0c;Tcp保证可靠性策略 3.1 确认应答机制&#xff08;核心&#xff09; 3.2 超时重传机制 3.3 …...

跨境支付专业术语

跨境支付 跨境支付是指支付或者清结算过程发生在两个及以上的国家地区之间、实现了资金跨国跨地区转移的支付行为。 境外本地支付 境外本地支付是指支付和清结算过程同时发生在单个国家或地区境内&#xff0c;资金在本国家或地区内部转移的支付行为。 国际汇款 国际汇款指跨…...

多级目录SQL分层查询

需求&#xff1a;有多级目录&#xff0c;而目录的层级是不固定的&#xff0c;如下图所示&#xff1a; 数据结构&#xff1a; sql语句&#xff1a; <select id"getList" resultType"com.hikvision.idatafusion.dhidata.bean.vo.knowledgebase.KnowledgeBaseT…...

VulnHub-SickOs1.1靶机笔记

SickOs1.1靶机笔记 概述 Vulnhub的靶机sickos1.1 主要练习从互联网上搜取信息的能力&#xff0c;还考察了对代理使用&#xff0c;目录爆破的能力&#xff0c;很不错的靶机 靶机地址&#xff1a; 链接: https://pan.baidu.com/s/1JOTvKbfT-IpcgypcxaCEyQ?pwdytad 提取码: yt…...

【Python】数据可视化之点线图

目录 散点图 气泡图 时序图 关系图 ​​​​​​​ 散点图 Scatterplot&#xff08;散点图&#xff09;是一种用于展示两个变量之间关系的图表类型。在散点图中&#xff0c;每个观测值&#xff08;或数据点&#xff09;都被表示为一个点&#xff0c;其中横轴&#xff08;…...

jupyter使用pytorch

1、激活环境 以下所有命令都在Anaconda Prompt中操作。 conda activate 环境名称我的环境名称是myenv 如果不知道自己的pytorch配在哪个环境&#xff0c;就用下面方法挨个试。 2、安装jupyter 1、安装 pip install jupyter2、如果已经安装&#xff0c;检查jupyter是否已…...

Electron 安装以及搭建一个工程

安装Node.js 在使用Electron进行开发之前&#xff0c;需要安装 Node.js。 官方建议使用最新的LTS版本。 检查 Node.js 是否正确安装&#xff1a; # 查看node版本 node -v # 查看npm版本 npm -v注意 开发者需要在开发环境安装 Node.js 才能编写 Electron 项目&#xff0c;但是…...

羽毛类型检测系统源码分享

羽毛类型检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…...

Xiaojie雷达之路---doa估计(dbf、capon、music算法)

Hello,大家好,我是Xiaojie,欢迎大家能够和Xiaojie来一起学习毫米波雷达知识,本篇文章主要是介绍一下雷达信号处理中的dbf、capon、music测角算法,一起来看看吧!!! 前言 本文从信号模型、dbf原理、capon原理、music原理以及代码仿真进行展开描述。 信号模型 阵列接收到…...

十大排序算法总结

完整文档见 排序算法总结——语雀文档 比较类排序&#xff1a;通过比较来决定元素间的相对次序&#xff0c;由于其时间复杂度不能突破O(nlogn)&#xff0c;因此也称为非线性时间比较类排序。 非比较类排序&#xff1a;不通过比较来决定元素间的相对次序&#xff0c;它可以突破…...

大厂AI必备数据结构与算法——链表(三)详细文档

冲冲冲&#xff01;开干 神马&#xff01;神马&#xff01;神马&#xff0c;一向让我们学习起来抓耳挠腮的数据结构课程竟然也有教程&#xff1f;还那么详细&#xff1f;&#xff1f;真的假的&#xff1f; 那么好&#xff0c;胡广告诉你是假的&#xff0c;哈哈哈哈哈哈哈哈哈…...

一键自动化配置OpenHarmony编译环境

一、概述 本工程旨在对Ubuntu一键初始化配置环境&#xff0c;解决OpenHarmony的编译依赖问题&#xff0c;基于本脚本配置后配合一键下载OpenHarmony代码便能轻松掌控OpenHarmony的下载、编译。 当前建议使用稳定分支Itopen-2.0-Release&#xff0c;该分支是经过多次测试OK的&…...

不同领域的常见 OOD(Out-of-Distribution)数据集例子

以下是几个来自不同领域的常见 OOD&#xff08;Out-of-Distribution&#xff09;数据集例子&#xff0c;这些数据集常用于测试和研究模型在分布变化或分布外数据上的泛化能力&#xff1a; 1. 计算机视觉领域 CIFAR-10 vs. CIFAR-10-C / CIFAR-100-C: 描述&#xff1a;CIFAR-10…...

gRPC协议简介

gRPC 是谷歌开源的一套 RPC 协议框架。主要做两件事情&#xff1a;一是数据编码&#xff0c;二是请求映射。 数据编码 数据编码顾名思义就是在将请求的内存对像转化成可以传输的字节流发给服务端&#xff0c;并将收到的字节流再转化成内存对像。方法有很多&#xff0c;常见的…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法

用神经网络读懂你的“心情”:揭秘情绪识别系统背后的AI魔法 大家好,我是Echo_Wish。最近刷短视频、看直播,有没有发现,越来越多的应用都开始“懂你”了——它们能感知你的情绪,推荐更合适的内容,甚至帮客服识别用户情绪,提升服务体验。这背后,神经网络在悄悄发力,撑起…...

Linux入门(十五)安装java安装tomcat安装dotnet安装mysql

安装java yum install java-17-openjdk-devel查找安装地址 update-alternatives --config java设置环境变量 vi /etc/profile #在文档后面追加 JAVA_HOME"通过查找安装地址命令显示的路径" #注意一定要加$PATH不然路径就只剩下新加的路径了&#xff0c;系统很多命…...