Go语言中什么时候使用指针

栏目: C · 发布时间: 5年前

内容简介:说明:理解本文的前提是你对Go语言已有一定的基础了解。什么是指针:即一个指针变量指向一个值的内存地址。使用值类型和指针类型的区别

说明:理解本文的前提是你对 Go 语言已有一定的基础了解。

什么是指针:即一个指针变量指向一个值的内存地址。

使用值类型和指针类型的区别

首先,我们来看一个计算面积的代码,如下所示。

package main

import (
	"fmt"
)

type Rect struct {                               //定义一个结构体
	width  float64
    length float64
}

func (rect Rect) area() float64 {               //定义一个方法,按值传递
	return rect.width * rect.length
}

func (rect *Rect) area1() float64 {            //定义一个方法,按指针传递
    rect.width *= 2
	rect.length *= 2
	return rect.width * rect.length
}

func main() {
	var rect = new(Rect)     //使用new函数创建一个结构体指针rect,也就是说rect的类型是*Rect
	rect.width = 100
	rect.length = 200
	fmt.Println("Width:", rect.width, "Length:", rect.length,"Area:", rect.area())  //通过结构体指针类型的变量调用area()方法
    fmt.Println("Width:", rect.width, "Length:", rect.length,"Area:", rect.area1())
}

在Go语言中,默认是按值传递。当一个变量当作参数传递的时候,会创建一个变量的副本,然后传递给函数或者方法,你可以看到这个副本的地址和变量的地址是不一样的。当变量当做指针被传递的时候,一个新的指针被创建,它指向变量同样的内存地址,所以你可以将这个指针看成原始变量指针的副本。

故此

1.是否使用结构体指针,取决于是否要在函数内部改变传递进来的参数的值。如果你的struct足够大,使用指针可以加快效率。如果不使用指针,在函数内部则无法修改struct中的值。

2.结构体赋值默认是按值传递,你要改变原来的那个值,要使用指针(即如果你要修改对象本身,那就要传指针,否则修改的是副本)。

再来比较下使用指针修改原始变量的值。代码示例

package main
import(
    "fmt"
)
 
func main(){ 
    i := 1      // i的类型是int型,值为1
    var p *int     // p 的类型是int型的指针
    p=&i         // p 的值为i的内存地址
    fmt.Printf("i=%d;p=%d;*p=%d\n",i,p,*p)
 
    *p=2    // *p 的值为i变量地址的指针 ,这行代码也就等价于 i := 2,使用指针修改变量本身
    fmt.Printf("i=%d;p=%d;*p=%d\n",i,p,*p)
 
    i := 3     // 验证想法
    fmt.Printf("i=%d;p=%d;*p=%d\n",i,p,*p)
}

以上输出结果为:

i=1;p=824633802904;*p=1
i=2;p=824633802904;*p=2
i=3;p=824633802904;*p=3

向函数传递指针参数

Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可。以下实例演示了如何向函数传递指针,并在函数调用后修改函数内的值,:

package main
import "fmt"

func main() {
   /* 定义局部变量 */
   var a int = 100
   var b int= 200

   fmt.Printf("交换前 a 的值 : %d\n", a )
   fmt.Printf("交换前 b 的值 : %d\n", b )

   /* 调用函数用于交换值
   * &a 指向 a 变量的地址
   * &b 指向 b 变量的地址
   */
   swap(&a, &b);

   fmt.Printf("交换后 a 的值 : %d\n", a )
   fmt.Printf("交换后 b 的值 : %d\n", b )
}

func swap(x *int, y *int) {
   var temp int
   temp = *x    /* 保存 x 地址的值 */
   *x = *y      /* 将 y 赋值给 x */
   *y = temp    /* 将 temp 赋值给 y */
}

输出结果为:

交换前 a 的值 : 100
交换前 b 的值 : 200
交换后 a 的值 : 200
交换后 b 的值 : 100

go什么情况下使用指针

  • 推荐在方法上使用指针(前提是这个类型不是 map、slice 等引用类型)
  • 当结构体较大的时候使用指针会更高效,可以避免内存拷贝,“结构较大” 到底多大才算大可能需要自己或团队衡量,如超过 5 个字段或者根据结构体内存占用来计算
  • 如果要修改结构体内部的数据或状态必须使用指针
  • 如果方法的receiver是map、slice 、channel等引用类型不要使用指针
  • 小数据类型如 bool、int 等没必要使用指针传递
  • 如果该函数会修改receiver或变量等,使用指针

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

分布式服务架构:原理、设计与实战

分布式服务架构:原理、设计与实战

李艳鹏、杨彪 / 电子工业出版社 / 2017-8 / 89.00

《分布式服务架构:原理、设计与实战》全面介绍了分布式服务架构的原理与设计,并结合作者在实施微服务架构过程中的实践经验,总结了保障线上服务健康、可靠的最佳方案,是一本架构级、实战型的重量级著作。 《分布式服务架构:原理、设计与实战》以分布式服务架构的设计与实现为主线,由浅入深地介绍了分布式服务架构的方方面面,主要包括理论和实践两部分。理论上,首先介绍了服务架构的背景,以及从服务化架构到微服务架......一起来看看 《分布式服务架构:原理、设计与实战》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

MD5 加密
MD5 加密

MD5 加密工具