go的接收器什么时候该用指针?|Go主题月

简介: 指针的两个关键符号*:返回所引用变量内存地址上的值&:返回变量的内存地址

指针的两个关键符号


  • *:返回所引用变量内存地址上的值
  • &:返回变量的内存地址

代码示例

首先可以看看下面这段代码的两个输出分别是什么?

package main
import (
  _ "embed"
  "fmt"
)
type person struct {
  Name    string
  Alias     string
  Summary     string
}
// 值接收器
func (p person) SetSummary() {
  p.Summary = fmt.Sprintf("我的名字叫%s,大家都叫我%s",p.Name,p.Alias)
}
// 指针接收器
func (p *person) SetSummaryByPointer() {
  p.Summary = fmt.Sprintf("我的名字叫%s,大家都叫我%s",p.Name,p.Alias)
}
func (p person) SaySummary() string {
  return p.Summary
}
func main(){
  per1 := person{Name:"程序员", Alias:"码农"}
  per1.SetSummary()
  fmt.Printf("第一段:%s\n",per1.SaySummary())
  per1.SetSummaryByPointer()
  fmt.Printf("第二段:%s\n",per1.SaySummary())
}

输出:

第一段:
第二段:我的名字叫程序员,大家都叫我码农

可以看到第一次SetSummary()的方法并为成功设置Summary字段的值,所以导致输出为空。而SetSummaryByPointer()却成功设置了Summary的值。

什么是接收器

首先我们要了解一下什么是接收器,看下面这张图就明白了。每个方法只能有一个接收器。

接收器类型可以是(几乎)任何类型,不仅仅是结构体类型,任何类型都可以有方法,甚至可以是函数类型,可以是 int、bool、string 或数组的别名类型,但是接收器不能是一个接口类型,因为接口是一个抽象定义,而方法却是具体实现,如果这样做了就会引发一个编译错误invalid receiver type…

网络异常,图片无法展示
|

值传递

为什么上面的SetSummary()方法没有成功设置Summary的值呢?

我们了解到在默认情况下Go 语言使用的是值传递,在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

所以接收器接收方(p在上面的示例中)的行为就好像它是该方法的参数一样。拥有和值传递一样的特性,方法里的修改对p来说是不可见的,因为它修改的只是p的副本数据。

而指针接收器也是接受了p的副本,但是它是p的地址副本,所以方法内修改是直接在对应的内存地址上进行了修改,所以原先p数据对应的地址发生了改变,p随之也发生改变。

总结


  1. 如果要修改接收器的值,则使用指针接收器
  2. 如果接收器很大,struct例如很大,优先考虑指针接收器
  3. 对于基本类型,切片和small之类的类型,structs值接收器效率更高
  4. 因此,除非该方法的语义要求使用指针,否则值接收器将高效且清晰。
相关文章
|
23天前
|
JSON Go 数据格式
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(4)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
23天前
|
Java 编译器 Go
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(3)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
23天前
|
存储 安全 Go
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(2)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
23天前
|
Java Go 索引
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(1)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
12天前
|
安全 测试技术 Go
Go语言在高并发场景下的应用
在当今互联网高速发展的时代,高并发已成为众多应用系统面临的核心问题。本文探讨了Go语言在高并发场景下的优势,并通过具体实例展示了其在实际应用中的效果和性能表现。
|
9天前
|
Go
go语言map、实现set
go语言map、实现set
14 0
|
9天前
|
Go
go语言数组与切片
go语言数组与切片
17 0
|
2天前
|
存储 Go API
一个go语言编码的例子
【7月更文挑战第2天】本文介绍Go语言使用Unicode字符集和UTF-8编码。Go中,`unicode/utf8`包处理编码转换,如`EncodeRune`和`DecodeRune`。`golang.org/x/text`库支持更多编码转换,如GBK到UTF-8。编码规则覆盖7位至21位的不同长度码点。
68 1
一个go语言编码的例子
|
5天前
|
JSON 算法 测试技术
在go语言中调试程序
【6月更文挑战第29天】Go语言内置`testing`包支持单元测试、基准测试和模糊测试。`go test`命令可执行测试,如`-run`选择特定测试,`-bench`运行基准测试,`-fuzz`进行模糊测试。
17 2
在go语言中调试程序
|
11天前
|
存储 中间件 Go
在go语言服务中封装路由和示例
【6月更文挑战第23天】本文介绍golang后端按协议处理、中间件(一次性与每次请求执行)划分、以及服务架构Controller、Logic/Service、DAO/Repository和Routers划分。代码仓库在GitHub上提供。使用框架简化了交互和处理。后续章节深入探讨服务构建。
107 5
在go语言服务中封装路由和示例