Go指南-结构体与指针

言淦 · · 1698 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

指针

指针其实跟变量一样,只不过普通变量存放的是数值,而指针变量存放的是数值的内存地址。

其中&符号表示对变量取地址,得到一个指针;*符号有两种用法,如果*后面跟的是指针,则表示对指针取值,即得到指针指向的值;如果如果*后面跟的是类型,则表示一个指向该类型的指针

Go文档的一个栗子:

func main() {
	i := 42 // 初始化一个值

	p := &i                   // &i表示对变量i取地址,并把地址赋给p,所以p是一个指针,指向i的值
	fmt.Println("pointer", p) // pointer 0xc000020078
	fmt.Println("value", *p)  // *表示对指针取值,即得到p指向的值,为42

	*p = 21        // 通过指针赋值
	fmt.Println(i) // 21

	var k *int // 这里的k是一个指针!!!
}

复制代码

注:Golang的指针不能进行计算。指针计算其实就是指针加减,在C语言中,是允许这样操作的,比如我们知道c语言中的数组名其实就是该数组的首地址,通过下标取值其实就是首地址的偏移,即加减。

结构体

Golang 里面的结构体(struct)可以类比面对对象语言中的类。

就像类有类方法一样,Golang也有结构体方法, 并且有带指针和不带指针的类方法。它们的区别具体如下:

type Rectangle struct {
	width int
	height int
}

func (r Rectangle) setWidth() {
	r.width = 100
}

func (r *Rectangle) setHeight() {
	r.height = 100
}

func main() {
	rec := Rectangle{width: 1, height: 1}
	rec.setWidth()
	fmt.Println(rec.width) // 仍然是1

	rec.setHeight()
	fmt.Println(rec.height)  // 变为100
}
复制代码

通过上面的例子可以看到,不带指针的方法(setWidth),传递的参数r其实是Rectangle的一份拷贝,所以即使在方法里面修改了width的值,原有的结构体并不受影响;而带指针的方法则相反。

官方文档也提到了这两者的区别:

  • 1.如果你需要在方法/函数内改变Rectangle的值,则必须声明一个指针方法。
  • 2.如果你的Rectangle结构体数据较大,比如有100个字段,如果使用不带指针的方法,则每一次都需要对其进行拷贝,内存消耗较大,此时建议使用带指针的方法。
  • 3.如果有部分方法是带指针的,则为了代码统一,建议其他方法也写成带指针的。

参考:
Should I define methods on values or pointers?

go struct 方法使用指针与不使用指针的区别?


有疑问加站长微信联系(非本文作者)

本文来自:掘金

感谢作者:言淦

查看原文:Go指南-结构体与指针

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1698 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传