接收器 接收器是一个参数,它指定了方法所属的类型。接收器可以是值接收器或指针接收器。值接收器会对接收器进行复制,而指针接收器不会。通常情况下,如果你需要修改接收器的状态,应该使用指针接收器。...例如,在上面的Rectangle结构体中,我们可以使用值接收器或指针接收器声明area()方法: // 值接收器 func (r Rectangle) area() float64 { return...在使用指针接收器时,方法会对原始值进行修改。 值接收器和指针接收器的选择 在选择值接收器或指针接收器时,需要考虑以下几个因素: 确定是否需要修改接收器的状态。...如果需要修改接收器的状态,则必须使用指针接收器。 确定方法的复杂度。如果方法非常简单,则可以使用值接收器。但是,如果方法非常复杂,则最好使用指针接收器,以避免复制大量的数据。 考虑性能。...使用值接收器比使用指针接收器更快,因为不需要额外的内存分配和解引用操作。但是,在处理大型结构时,指针接收器可能更有效率。 接口 接口是一种抽象类型,它描述了对象的行为。
方法接收器可以是一个值类型(如 struct 或自定义类型),也可以是指向一个值类型的指针类型。 值接收器 值接收器是将类型的值作为方法接收器。...这意味着任何 Person 类型的值或指针都可以调用 SayHello 方法,例如: p := Person{Name: "陈明勇", Age: 23} p.SayHello() p2 := &Person...{Name: "陈明勇", Age: 23} p2.SayHello() 指针接收器 指针接收器是将类型的指针作为方法接收器。...指接收器可以接收类型的值和指针,如果是指针,在方法内部会被转为值。 指针接收器 当使用指针接收器时,方法内部对接收器的修改会影响到原始值。...因为值接收器会创建原始值的副本,在方法内部对其进行的修改 不会 影响原始值。 数据结构大小:对于大型数据结构,使用 指针接收器 可以避免数据复制带来的性能开销。
Like- 通过 PointerReceiver 方法将人的年龄从 68 岁更改为 24 岁,同样的变化反映在 main 方法中。您可以通过在指针或值接收器操作之前和之后打印出对象的地址来检查事实。...如果接收器是一个大型结构,这可能会更有效, 值接收器是并发安全的,而指针接收器不是并发安全的。因此,程序员需要照顾它。...如果接收者是包含sync.Mutex或类似同步字段的结构,则接收者必须是指针以避免复制。 如果接收器是大型结构或数组,则指针接收器效率更高。大有多大?假设它相当于将其所有元素作为参数传递给方法。...如果更改必须在原始接收器中可见,则接收器必须是指针。 如果接收器是结构体、数组或切片,并且它的任何元素都是指向可能发生变化的东西的指针,则更喜欢指针接收器,因为它会使读者更清楚意图。...如果接收者是一个小数组或结构,它自然是一个值类型(例如,类似time.Time类型),没有可变字段和指针,或者只是一个简单的基本类型,如 int 或 string,则值接收器更好。
在校验失败的情况下,会分配一个MultiError对象给它,并且向它里面Add一个error。在最后将m返回,此时m的值要么是nil要么是指向MultiError对象的指针。...= nil条件,输出的log日志打中为nil,这是为什么呢? 在Go语言中,我们知道一个指针接收器可以是nil. 下面创建一个假类型并使用它的nil指针接收器调用方法进行验证。...被初始化为指针的零值(nil), 如果Age和Name都合法,返回值不是直接的nil而是nil指针。...由于nil指针是一个有效的接收器,返回的结果不再是nil值,而是被转换为interface。换句话说,Validate的调用方法将总是会得到一个非零错误。...总结,在Go语言中,允许使用nil作为函数的接收器,而从nil指针转换的接口不再是nil接口。因此,当我们必须返回一个接口时,不应该直接返回一个nil指针,而应该是一个nil值。
名字 别的类型 • type 别名 = 别的类型 • 结构体初始化 • 指针与方法接收器 • 结构体如何实现接口 接口(Interface):接口定义了一组方法的集合,这些方法可以由实现接口的任何类型的值进行调用...,只能使用指针 • 准确来说,在整个引用链上,如果构成循环,那就只能用指针 必须使用指针 方法接收器 结构体接收器内部永远不要修改字段 在Go语言中,结构体接收器内部永远不要修改字段,主要是为了遵循良好的编程实践和保持代码的可读性与可维护性...结构体和指针之间的方法可以互相调用 设计不可变对象,用结构体接收器 总结:遇事不决用指针 结构体如何实现接口 当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。...当一个结构体具备接口的所有的方法的时候,它就实现了这个接口 实现看到自己定义的 不带* 的为结构体接收器 带 * 的为指针接收器 如何查看实现的接口 点击箭头会自动跳转 注释规范 可以看到 Golang...其中 type A=B 这种别名,一般只用于兼容性处理 • 先有抽象再有实现,所以要先定义接口 • 鸭子类型:一个结构体有某个接口的所有方法,它就实现了这个接口 • 指针:方法接收器,遇事不决用指针 最后
接收器的存在提供了方法对其所属类型实例的访问能力,这对于设计清晰且富有表达力的API非常有用。接收器与值传递的区别非指针接收器:当接收器不是指针时,方法作用的是接收器的一个副本(值传递)。...为什么有些方法既有接收器又有值传递在某些情况下,方法不仅需要访问或修改其接收器代表的数据,还需要处理额外的输入参数。...这些参数可以是值传递,也可以是引用传递,具体取决于是否需要在方法内部修改它们或考虑到性能优化(如大型结构的传递)。...Add方法将接收两个矩阵实例作为值传递的参数,并返回它们的和的新矩阵实例;而Multiply方法将使用指针接收器来修改当前矩阵实例,并将另一个矩阵作为值传递参数来执行矩阵乘法。...而直接传递指针参数通常需要在方法外部处理返回的指针。可读性和意图表达:指针接收器清楚地表明方法将修改接收器的状态,而直接传递指针参数可能需要更多的上下文来理解其意图。
指针接收器VS值接收器实现接口 在前面的文章中其实我们主要使用值接收器来实现接口,比如下面这样: package main import ( "fmt" ) type Worker interface...因此,我们既可以用值作为函数的接收器实现接口,也可以用指针作为函数的接收器实现接口,但是需要注意的是,对于使用指针作为函数接收器实现时,我们在使用时,也只能用指针调用。...,如果我们想要改变接收的数据的值,比如代码中要改变 a 也就是 Address 类型的数据中参数的值,就用指针作为函数接收器,相反则用值作为函数接收器。...,分别是 SalaryCalculator 和 LeaveCalculator,Employee 结构体实现了 SalaryCalculator 接口中的 DisplaySalary 方法和 LeaveCalculator...,所以程序最后输出: d1 is nil and has type value 如果我们尝试调用 nil 接口的方法,程序就会报 panic 错误,因为 nil 接口既没有底层值
实现包应返回具体(通常是指针或结构)类型:这样一来可以将新方法添加到实现中,而无需进行大量重构。...此常见实例包括将指针传递给 string(string)或是指向接口值(*io.Reader)的指针。在这两种情况下,值本身都是固定大小,可以直接传递。...如有疑问,请使用指针接收器,但有时候值接收器是有意义的,通常是出于效率的原因,例如小的不变结构或基本类型的值。...如果该方法需要改变接收器的值,则接收器必须是指针。 如果接收器是包含 sync.Mutex 或类似同步字段的 struct,则接收器必须是避免复制的指针。...如果接收器是大型结构或数组,则指针接收器更有效。多大才算大?假设它相当于将其包含的所有元素作为参数传递给方法。如果感觉太大,那么对接收器来说也太大了。
一、Go支持指针,允许在程序中通过引用传递值或者数据类型 在这里我们分别创建两个包含值类型和引用类型参数的函数 func zeroval(ival int) { ival = 0 } func...,依旧是1 而指针类型的参数值则发生了改变 在上面 *i 是创建了一个指针类型,&i 是获取指针的地址中的值,在上面示例中&i取到i的指针地址值 然后在zeroptr函数中将地址的地址的值重新赋予了一下...: "fuck”}) // & 前缀生成一个结构体指针 fmt.Println(&person{name: "bob", age: 23}) 三、方法 Go支持在结构体类型中定义方法 方法在func关键字和方法名中间加入了一个特殊的接收器类型...,接收器可以是结构体类型或者是非结构体类型 接收器是可以在方法的内部访问的 创建方法的语法: rect是一个结构体 area() 方法将rect作为一个接收器类型 func (r *rect) area...在Go语言中,接口 是方法特征的命名集合 声明一个几何体接口 在Go语言中,可以通过type 接口名称 interface 的方式定义接口 在接口中,可以指定多个方法 在方法实现接口时,需要实现接口下面的所有方法
}值接收器和指针接收器方法的接收器有两种:值接收器和指针接收器。...当通过类型变量调用方法时,会把调用者复制给接收器,无论是值接收器还是指针接收器,都会发生复制,所不同的是,使用值接收器时,会把调用者的值复制给接收器,使用指针接收器时,会把调用者的内存地址复制给接收器。...,该教室包含100个学生(Student)的信息,ChangeName1()方法使用的是值接收器,ChangeName2()方法使用的是指针接收器。...接收器的命名惯例指针接收器的作用类似面向对象编程类的this,用于引用对象自身,不过Go并不推荐将接收器命名为this,而是推荐使用接收器类型的首字母小写:go 代码解读复制代码type Reason...最后,总结一下,阅读完这篇文章后应该掌握的几个知识点:自定义类型是什么,如何自定义数据类型方法是什么,如何创建与调用方法。接收器是什么?什么是指针接收器,什么是值接收器。什么情况下要用指针接收器。
上文已经提及,Go 语言结构体并非 Java 和 C++ 语言中 class 的概念,下面我们来了解一下结构体变量声明和相关函数调用在机器码或汇编层面的体现。我们以下面代码为案例进行分析。...值接收器函数 下面我们来看一下结构体作为函数接收器如何进行函数调用,包括如何如何传递参数和返回值,如何进行值接收器和指针接收器转换等。...a 累加,其位置为 +56(SP) 将二者的和赋值给变量 n,并且将二者的和保存到返回值所在栈空间,也就是 +64(SP); 从 8(SP) 中取出旧栈帧指针,并且将栈帧缩小 16 字节,并调用 RET...指针接收器函数 下面,我们来看调用指针接收器函数 addAgePtr 相关的具体指令,体会它与值接收器函数的区别。...此外,调用 addAgePtr 的场景是在值变量上调用指针接收器函数,我们看到编译器将值的地址取出作为接收器参数进行传递,而如果是指针变量调用值接收器函数的话,则会先对指针进行取地址,然后再将指针指向的值数据进行拷贝
Gopher常犯的一个错误是不了解参数是如何计算求值的,本节内容将分两个小节深入研究此问题:第一个与函数或方法参数有关,第二与方法接收器有关....采用这种方法,程序可以如预期运行并且不改变notify和incrementCounter的函数签名。 下面开始讨论在带有指针或值接收器的方法上使用defer会产生什么效果呢?...指针或值接收器计算求值 在Go语言中常见100问题-#42 Not knowing which type of receiver to use节中讨论了接收器可以是值类型也可以是指针类型。...但是,它复制的是指针的值。因此,对指针引用的结构所做的任何更改在延迟函数执行时是可见的。所以上面的程序会输出bar. 总结,在函数或方法上调用defer时,调用的参数会立即被计算。...如果我们想改变提供给defer的参数,我们可以使用指针或闭包。对于一个方法,接收器也是立即被计算,具体的行为结果取决于接收器是值还是指针。
然而,如果一个defer函数带有参数,那么这些参数是如何被取值的呢? 本文会深入讨论在defer函数中参数取值以及带指针或值接受者的defer。...2 带指针和值接受器的defer 当给一个方法指定接收者的时候,这个接收者可以是一个值拷贝,也可以是一个指针。简单来说,就是指针接收器可以修改接收器指向的值。想反,值拷贝接收器是原类型值的一个拷贝。...该方法有一个值接收器,因此defer将调度该方法的执行,此时该方法的接收器是一个包含id字段值为foo的结构体。因此,该例子的输出是 foo。...然而,该指针引用了一个结构体,该结构体的值在函数返回前发生了变化。因此,该实例的输出是bar。 3 小结 总之,在一个方法或函数上调用defer,调用的参数是被立即取值的。...对于一个方法来说,接收器也是被立即取值的。如果我们想要延迟取值,可以通过使用指针或闭包的方式来实现。
Nil也是一个合法的接收器类型 就像一些函数允许nil指针作为参数一样,方法理论上也可以用nil指针作为其接收器,尤其当nil对于对象来说是合法的零值时,比如map或者slice。...当Point.Distance被第一个包装方法调用时,它的接收器值是p.Point,而不是p,当然了,在Point类的方法里,你是访问不到ColoredPoint的任何字段的(笔者注:即被嵌套结构体不能访问嵌套结构体的任何字段...p.Distance叫作“选择器”,选择器会返回一个方法值"->**一个将方法(Point.Distance)绑定到特定接收器变量的函数。...UnionWith这个方法里用到了bit位的“或”逻辑操作符号|来一次完成64个元素的或计算。 当前这个实现还缺少了很多必要的特性,下面我们将IntSet作为一个字符串来打印。...在这章中,我们学到了如何将方法与命名类型进行组合,并且知道了如何调用这些方法。尽管方法对于OOP编程来说至关重要,但他们只是OOP编程里的半边天。为了完成OOP,我们还需要接口
第 12 章 方法 方法 其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的。..., } lesson.PrintInfo() author := Author{"欢喜"} author.PrintInfo() } 12.2 指针接收器与值接收器 值接收器和指针接收器之间的区别在于...,在指针接收器的方法内部的改变对于调用者是可见的,然而值接收器的方法内部的改变对于调用者是不可见的,所以若要改变实例的属性时,必须使用指针作为方法的接收者。...12.3 在方法中使用值接收器 与 在函数中使用值参数 当一个函数有一个值参数,它只能接受一个值参数。当一个方法有一个值接收器,它可以接受值接收器和指针接收器。...12.4 在非结构体上的方法 不仅可以在结构体类型上定义方法,也可以在非结构体类型上定义方法,但是有一个问题。为了在一个类型上定义一个方法,方法的接收器类型定义和方法的定义应该在同一个包中。
在现实的程序里,一般会约定如果Point这个类有一个指针作为接收器的方法,那么所有Point的方法都必须有一个指针接收器,即使是那些并不需要这个指针接收器的函数。...,就算你对其进行了拷贝(指针调用时也是值拷贝,只不过指针的值是一个内存地址,所以在函数里的指针与调用方的指针变量是两个不同的指针但是指向了相同的内存地址)。...Nil也是一个合法的接收器类型 就像一些函数允许nil指针作为参数一样,方法理论上也可以用nil指针作为其接收器,尤其当nil对于对象来说是合法的零值时,比如map或者slice。...p.Distance叫作“选择器”,选择器会返回一个方法"值"->一个将方法(Point.Distance)绑定到特定接收器变量的函数。...比如下面的Counter类型允许调用方来增加counter变量的值,并且允许将这个值reset为0,但是不允许随便设置这个值(译注:因为压根就访问不到): type Counter struct {
指南 指向接口的指针 几乎不需要使用指向接口的指针。即使底层数据是指针,接口也应作为值传递。 验证接口合规性 在适当的地方编译时验证接口合规性,以确保类型实现了所需的接口。...带有值接收器的方法可以在值和指针上调用,而带有指针接收器的方法只能在指针或可寻址的值上调用。...零值 Mutex 是有效的 sync.Mutex 和 sync.RWMutex 的零值是有效的,因此很少需要指向 mutex 的指针。...= nil { log.Fatal(err) } } func run() error { // ... } 在序列化结构体中使用字段标签 在序列化为 JSON、YAML 或其他格式的结构体中使用字段标签...k := User{ FirstName: "John", LastName: "Doe", } 省略结构体中的零值字段 初始化结构体时省略零值字段。
,Text和Name相当于类中的成员变量,(a *A) Say()中的a是A结构体变量作为方法接收器,实现了类的成员方法。...方法接收器类型用结构体还是结构体指针 先要了解一件事:go语言中的结构体是值类型的,不是指针类型的。在Go语言中,除了map、slice和chan,所有类型(包括struct)都是值传递的。...其相当于: 篇外话:并不是只有结构体才能绑定方法,任何类型都可以绑定方法,只是我们这里介绍将方法绑定到结构体中。...结构体方法是要将接收器定义成值,还是指针。这本质上与函数参数应该是值还是指针是同一个问题。 方法接收器为何不推荐用this,self 虽然看到不少人不少地方这么用,但还是不推荐。...若不是一般写法,就是方法接收器不是结构体指针,而是结构体的情形,那么不会对类中成员变量做任何修改,和this,self的意义完全不符,这时候用this,self会带到沟里去。
一个例外情况是当前方法签名必须与标准库或第三方库中的接口方法匹配。不要在函数签名中创建自定义 Context 类型或使用除了 Context 以外的接口。...Go 接口通常属于使用 interface 类型值的包,而不是实现这些值的包。实现包应返回具体(通常是指针或结构)类型。...名称可以非常短,因为它几乎出现在每种类型的每个方法的每一行上。 接收器什么时候使用值或者指针: (1)小的不变结构或基本类型可以用值接收器。这样可以提高效率。...(2)在你不确定是使用值还是指针作为接收器时,请用指针接收器。 (3)如果该方法需要改变接收器的值,则接收器必须是指针。 (4)如果接收器是 map,func或 chan,则不要使用指向它们的指针。...如果接收器是 slice 并且该方法不重新切片或不重新分配切片,则不要使用指向它的指针。 Go 语言规范工具 go 的官方工具链做得很好,可以直接使用gofmt和golint检查代码规范。
另一方面,方法是附加到给定类型的函数。附加类型称为接收器接收器,可以是指针或值。本章一开始我们讨论如何选择一种接收机类型,因为这通常是一个争论的来源。...此外,在许多情况下,使用值或指针接收器不应该由性能决定,而是由我们将讨论的其他条件决定。但首先,让我们回忆一下接收器是如何工作的。 在 Go 中,我们可以给一个方法附加一个值或者一个指针接收器。...因为我们使用了一个值接收器,所以在add方法中增加余额不会改变原始customer结构的balance字段: 100.00 另一方面,使用指针接收器,Go 将对象的地址传递给方法。...混合接收器类型 我们是否可以混合接收器类型,比如一个包含多个方法的结构,其中一些有指针接收器,另一些有值接收器?共识倾向于禁止它。不过标准库中也有一些反例,比如time.Time。...然后,如果所有的检查都有效,那么提供给return语句的参数不是直接提供给nil,而是一个空指针。因为nil指针是一个有效的接收器,所以将结果转换成接口不会产生nil值。
领取专属 10元无门槛券
手把手带您无忧上云