概述
很多人(特别是新手)在写 Go 语言代码时经常会问一个问题,那就是一个方法的接受者类型到底应该是值类型还是指针类型呢,Go 的 wiki 上对这点做了很好的解释,我来翻译一下。
何时使用值类型
1.如果接受者是一个 map,func 或者 chan,使用值类型(因为它们本身就是引用类型)。
2.如果接受者是一个 slice,并且方法不执行 reslice 操作,也不重新分配内存给 slice,使用值类型。
3.如果接受者是一个小的数组或者原生的值类型结构体类型(比如 time.Time 类型),而且没有可修改的字段和指针,又或者接受者是一个简单地基本类型像是 int 和 string,使用值类型就好了。
一个值类型的接受者可以减少一定数量的垃圾生成,如果一个值被传入一个值类型接受者的方法,一个栈上的拷贝会替代在堆上分配内存(但不是保证一定成功),所以在没搞明白代码想干什么之前,别因为这个原因而选择值类型接受者。
何时使用指针类型
1.如果方法需要修改接受者,接受者必须是指针类型。
2.如果接受者是一个包含了 sync.Mutex 或者类似同步字段的结构体,接受者必须是指针,这样可以避免拷贝。
3.如果接受者是一个大的结构体或者数组,那么指针类型接受者更有效率。(多大算大呢?假设把接受者的所有元素作为参数传给方法,如果你觉得参数有点多,那么它就是大)。
4.从此方法中并发的调用函数和方法时,接受者可以被修改吗?一个值类型的接受者当方法调用时会创建一份拷贝,所以外部的修改不能作用到这个接受者上。如果修改必须被原始的接受者可见,那么接受者必须是指针类型。
5.如果接受者是一个结构体,数组或者 slice,它们中任意一个元素是指针类型而且可能被修改,建议使用指针类型接受者,这样会增加程序的可读性
当你看完这个还是有疑虑,还是不知道该使用哪种接受者,那么记住使用指针接受者。
关于接受者的命名
社区约定的接受者命名是类型的一个或两个字母的缩写(像 c 或者 cl 对于 Client)。不要使用泛指的名字像是 me,this 或者 self,也不要使用过度描述的名字,最后,如果你在一个地方使用了 c,那么就不要在别的地方使用 cl。
问题内容: 根据这个问题的回答 关于指针与接收器的值的规则是,可以在指针和值上调用值方法,但是只能在指针上调用指针方法 但实际上我可以对非指针值执行指针方法: 那么,这是怎么了?这是新功能吗?还是对问题的回答是错误的? 问题答案: 您正在对指针值调用“指针方法”。在表达式中: 是类型(非指针);由于该方法具有指针接收者,并且由于接收者值是非指针且可寻址,因此它是以下各项的简写形式: 这是在规范中:
主要内容:将值保存到空接口,从空接口获取值,空接口的值比较空接口是接口类型的特殊形式,空接口没有任何方法,因此任何类型都无须实现空接口。从实现的角度看,任何值都满足这个接口的需求。因此空接口类型可以保存任何值,也可以从空接口中取出原值。 提示 空接口类型类似于 C# 或 Java 语言中的 Object、C语言中的 void*、 C++ 中的 std::any。在泛型和模板出现前,空接口是一种非常灵活的数据抽象保存和使用的方法。 空接口的内部实现保存了对
一个布尔类型的值只有两种:true 或 false。if 和 for 语句的条件部分都是布尔类型的值,并且 和 等比较操作也会产生布尔型的值。 一元操作符 对应逻辑非操作,因此 的值为 false,更复杂一些的写法是 ,实际开发中我们应尽量采用比较简洁的布尔表达式,就像用 x 来表示 。 Go语言对于值之间的比较有非常严格的限制,只有两个相同类型的值才可以进行比较,如果值的类型是接口(interf
类型断言(Type Assertion)是一个使用在接口值上的操作,用于检查接口类型变量所持有的值是否实现了期望的接口或者具体的类型。 在Go语言中类型断言的语法格式如下: value, ok := x.(T) 其中,x 表示一个接口的类型,T 表示一个具体的类型(也可为接口类型)。 该断言表达式会返回 x 的值(也就是 value)和一个布尔值(也就是 ok),可根据该布尔值判断 x 是否为 T
问题内容: Go spec说: 其他任何类型T的方法集都包含接收者类型T的所有方法。相应指针类型 T的方法集是接收者 T或T的所有方法的集合(也就是说,它还包含T)。 我的理解是:T有自己的方法集,而 T有自己的方法集加上T的方法集,因为它可以将接收者 T取消引用到T并调用该方法。因此,我们可以使用变量T的接收者* T调用某些方法。 因此,我决定验证自己的逻辑: http://play.golan
Go语言提供了两种精度的浮点数 float32 和 float64,它们的算术规范由 IEEE754 浮点数国际标准定义,该浮点数规范被所有现代的 CPU 支持。 这些浮点数类型的取值范围可以从很微小到很巨大。浮点数取值范围的极限值可以在 math 包中找到: 常量 math.MaxFloat32 表示 float32 能取到的最大数值,大约是 3.4e38; 常量 math.MaxFloat64