目录
值类型和指针类型
值类型和指针类型
方法也有值类型的方法和指针类型的区别,也就是以下两种receiver:
func (p person) setname(name string) { p.name = name }
func (p *person) setage(age int) { p.age = age }
setname()方法中是值类型的receiver,setage()方法中是指针类型的receiver。它们是有区别的。
- 首先,setage()方法的p是一个指针类型的person实例,所以方法体中的
p.age
实际上等价于(*p).age
。再者,方法就是函数,Go中所有需要传值的时候,都是按值传递的,也就是拷贝一个副本。
setname()中,除了参数name string
需要拷贝,receiver部分(p person)
也会拷贝,而且它明确了要拷贝的对象是值类型的实例,也就是拷贝完整的person数据结构。但实例有两种类型:值类型和指针类型。
-
(p person)
无视它们的类型,因为receiver严格规定p是一个值类型的实例。所以无论是指针类型的p1实例还是值类型的p2实例,都会拷贝整个实例对象。对于指针类型的实例p1,前面说了,在需要的时候,Go会自动解除引用,所以p1.setname()
等价于(*p1).setname()
。
只要receiver是值类型的,无论是使用值类型的实例还是指针类型的实例,都是拷贝整个底层数据结构的,方法内部访问的和修改的都是实例的副本。所以,如果有修改操作,不会影响外部原始实例。
-
setage()中,receiver部分
(p *person)
明确指定了要拷贝的对象是指针类型的实例,无论是指针类型的实例p1还是值类型的p2,都是拷贝指针。所以p2.setage()
等价于(&p2).setage()
。
也就是说,只要receiver是指针类型的,无论是使用值类型的实例还是指针类型的实例,都是拷贝指针,方法内部访问的和修改的都是原始的实例数据结构。所以,如果有修改操作,会影响外部原始实例。
那么选择值类型的receiver还是指针类型的receiver?一般来说选择指针类型的receiver。
package main
import "fmt"
type person struct {
name string
age int
}
func (p person) setname(name string) {
p.name = name
}
func (p *person) setage(age int) {
p.age = age
}
func (p *person) getname() string {
return p.name
}
func (p *person) getage() int {
return p.age
}
func main() {
// 指针类型的实例
p1 := new(person)
p1.setname("longshuai1")
p1.setage(21)
fmt.Println(p1.getname()) // 输出""
fmt.Println(p1.getage()) // 输出21
// 值类型的实例
p2 := person{}
p2.setname("longshuai2")
p2.setage(23)
fmt.Println(p2.getname()) // 输出""
fmt.Println(p2.getage()) // 输出23
}
上面分别创建了指针类型的实例p1和值类型的实例p2,但无论是p1还是p2,它们调用setname()方法设置的name值都没有影响原始实例中的name值,所以getname()都输出空字符串,而它们调用setage()方法设置的age值都影响了原始实例中的age值。文章来源:https://www.toymoban.com/news/detail-409335.html
方法不过是一种特殊的函数,只需将其还原,就知道 receiver T 和 *T
的差别。文章来源地址https://www.toymoban.com/news/detail-409335.html
package main
import "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 := &d
fmt.Printf("Data: %p\n", p)
d.ValueTest() // ValueTest(d)
d.PointerTest() // PointerTest(&d)
p.ValueTest() // ValueTest(*p)
p.PointerTest() // PointerTest(p)
}
到了这里,关于【Go进阶】详解方法的值类型和指针类型区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!