Go 语言指针

Go 语言中指针是很容易学习的,Go 语言中使用指针可以更简单的执行一些任务。

接下来让我们来一步步学习 Go 语言指针。

我们都知道,变量是一种使用方便的占位符,用于引用计算机内存地址。

Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。

以下实例演示了变量在内存中地址:

 package main

 import (
"fmt"
) func main(){
var name string
name = "demon"
fmt.Println("name变量的指针地址:",&name)
}

以上代码运行返回的结果:

name变量的指针地址: 0xc420076050

什么是指针

一个指针变量可以指向任何一个值的内存地址它指向那个值的内存地址。

类似于变量和常量,在使用指针前你需要声明指针。指针声明格式如下:

var var_name(变量名) *var_name_type(数据类型)

var_name就是变量的名称,var_name_type是指针的数据类型,*用于指定变量是一个指针,例如以下的指针声明

var name *string            //指向字符串类型的指针
var age *int //指向整数型类型的指针

如何使用指针

指针使用流程:

  • 定义指针变量。
  • 为指针变量赋值。
  • 访问指针变量中指向地址的值。

在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。

 package main

 import (
"fmt"
) func main(){
//定义局部变量num1 num2
var num1 int =
var num2 *int //获取num1变量的内存地址并赋值给num2变量
num2 = &num1 fmt.Println("num1变量的内存地址为:", &num1)
fmt.Println("num2变量指针的地址为:", num2) //获取变量num1的值
fmt.Println("num1变量的值为:", num1)
//获取变量num2的值
fmt.Println("num2变量的值为:", *num2) }

以上代码返回的运行结果:

num1变量的内存地址为: 0xc42006e178
num2变量指针的地址为: 0xc42006e178
num1变量的值为:
num2变量的值为:

Go 空指针

当一个指针被定义后没有分配到任何变量时,它的值为 nil。

nil 指针也称为空指针。

nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。

一个指针变量通常缩写为 ptr。

查看以下实例:

 package main

 import (
"fmt"
) func main(){
//初始化局部变量 ptr s 分别都是空指针
var ptr *int
var s *string
//初始化局部变量num1 num2,因为num1赋值了并且num2的指针指向了num1
var num1 float32 = 50.123
var num2 *float32
num2 = &num1 //分别输出变量的值
fmt.Printf("ptr的空指针的值为:%v\n", ptr)
fmt.Printf("s的空指针的值为:%v\n", s)
fmt.Printf("num2的值为%v\n", *num2) //做判断,如果是空指针的话值就是nil
if ptr == nil{
fmt.Println("ptr是空指针哦~")
} if s == nil{
fmt.Println("s是空指针哦~")
} if num2 == nil{
fmt.Println("num2的是空指针哦~")
}else {
fmt.Println("num2的值为:", *num2)
} }

以上代码返回的运行结果:

ptr的空指针的值为:<nil>
s的空指针的值为:<nil>
num2的值为50.
ptr是空指针哦~
s是空指针哦~
num2的值为: 50.123

Go 语言指针数组

number为整型指针数组。因此每个元素都指向了一个值。以下实例的三个整数将存储在指针数组中:

 package main

 import (
"fmt"
) func main(){
//定义一个blance数组,并且拥有五个元素
var blance = [] int {,,,,}
//定义常量MAX为5
const MAX int =
//定义数组指针number
var number [MAX] *int for i := ; i< MAX; i++{
//分别给number的数组中的每个索引赋值,值是引用blance数组中的每个元素的内存地址
number[i] = &blance[i]
fmt.Printf("blance[%d] = %d \n", i, blance[i])
} fmt.Println("----------------------") for i := ; i< MAX; i++{
fmt.Printf("number[%d] = %d \n", i, *number[i])
} fmt.Println("----------------------") for i := ; i< MAX; i++{
//如果blance数组与number数组一样,并且里面只的内存地址都一样,则打印两个数组元素的内存地址
if blance[i] == *number[i] && &blance[i] == number[i]{
fmt.Printf("blance[%d] %v number[%d] %v \n",i , &blance[i], i ,number[i]) }
}
}

以上代码返回的运行结果:

blance[] =
blance[] =
blance[] =
blance[] =
blance[] =
----------------------
number[] =
number[] =
number[] =
number[] =
number[] =
----------------------
blance[] 0xc4200141e0 number[] 0xc4200141e0
blance[] 0xc4200141e8 number[] 0xc4200141e8
blance[] 0xc4200141f0 number[] 0xc4200141f0
blance[] 0xc4200141f8 number[] 0xc4200141f8
blance[] 0xc420014200 number[] 0xc420014200

来来来来,用Python来嘲讽一波golang的数组引用赋值~

 #!/usr/bin/env python3
# _*_coding:utf-8_*_ __author__ = 'demon' #声明列表l1
l1 = ['demon','','beijing',"python","golang","linux"]
#浅拷贝列表l1中的每个元素
l2 = l1[:] l1_len = len(l1) for i in range(l1_len):
#判断列表中每个元素的内存地址是否一致
if id(l1[i]) == id(l2[i]):
#打印两个列表中给的每个元素及内存地址
print("l1[{}] {:10} l2[{}] {:10} at {memory}".format(i,l1[i],i,l2[i],memory=id(l1[i])))

以上代码返回的运行结果:

l1[0]   demon        l2[0]  demon      at 4302152624
l1[1] 18 l2[1] 18 at 4330894536
l1[2] beijing l2[2] beijing at 4330894200
l1[3] python l2[3] python at 4329981408
l1[4] golang l2[4] golang at 4330894984
l1[5] linux l2[5] linux at 4329974728

Go 语言指向指针的指针

如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。

当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址:

指向指针的指针变量声明格式如下:

var ptr **int;

以上指向指针的指针变量为整型。

访问指向指针的指针变量值需要使用两个 * 号,如下所示:

 package main

 import (
"fmt"
) func main() { var a int
var ptr *int
var pptr **int a = //指针ptr地址
ptr = &a //指向指针ptr地址
pptr = &ptr //*获取pptr的值
fmt.Printf("变量 a = %d\n", a )
fmt.Printf("指针变量 *ptr = %d\n", *ptr )
fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr)
}

以上代码返回的运行结果:

变量 a =
指针变量 *ptr =
指向指针的指针变量 **pptr =

Go 语言指针作为函数参数

Go 语言允许向函数传递指针,只需要在函数定义的参数上设置为指针类型即可。

以下实例演示了如何向函数传递指针,并在函数调用后修改函数内的值:

 package main

 import (
"fmt"
) //可以接收指针作为参数的自定义函数
func person(name *string,age *int) string {
//修改指针指向的name变量的值,影响了name的值
*name = "大佬"
fmt.Println("person函数内部的name的内存地址:", name)
fmt.Printf("person函数内部的修改后name变量值:%s", *name)
return "" } func swap(x ,y int) string{
//修改x,y的值,x,y作为局部变量传递进来,因为没有使用指针,所以不会影响函数外部的x,y变量值
x, y = ,
fmt.Println("swap函数内部的x变量值:", x)
fmt.Println("swap函数内部的y变量值:", y)
return ""
} func main() {
//初始化局部变量
var name string = "demon"
var age int =
var x int =
var y int = fmt.Println("person函数内部的修改后name变量值:", name)
fmt.Println("person函数外部的name的内存地址:", &name)
fmt.Println(person(&name, &age))
fmt.Printf("person函数外部的修改后name变量值:%s \n",name) fmt.Println("--------------------------------------------")
fmt.Println(swap(x,y ))
fmt.Println("swap函数外部的x变量值:", x)
fmt.Println("swap函数外部的y变量值:", y) }

以上代码返回的运行结果:

person函数内部的修改后name变量值: demon
person函数外部的name的内存地址: 0xc42006e1a0
person函数内部的name的内存地址: 0xc42006e1a0
person函数内部的修改后name变量值:大佬
person函数外部的修改后name变量值:大佬
--------------------------------------------
swap函数内部的x变量值:
swap函数内部的y变量值: swap函数外部的x变量值:
swap函数外部的y变量值:

Go指针的更多相关文章

  1. TODO:Golang指针使用注意事项

    TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...

  2. enote笔记法使用范例(2)——指针(1)智能指针

    要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...

  3. C++虚函数和函数指针一起使用

    C++虚函数和函数指针一起使用,写起来有点麻烦. 下面贴出一份示例代码,可作参考.(需要支持C++11编译) #include <stdio.h> #include <list> ...

  4. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  5. c 数组与指针的使用注意事项

    数组变量和指针变量有一点小小的区别 所以把数组指针赋值给指针变量的时候千万要小心 加入把数组赋值给指针变量,指针变量只会包含数组的地址信息 而对数组的长度一无所知 相当于指针丢失了一部分信息,我们把这 ...

  6. Marshal.Copy将指针拷贝给数组

    lpStatuss是一个UNITSTATUS*的指针类型实例,并包含SensorDust字段 //定义一个数组类型 byte[] SensorDust = new byte[30] //将指针类型拷贝 ...

  7. C++智能指针

    引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...

  8. EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针

    一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...

  9. 智能指针shared_ptr的用法

    为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...

  10. 智能指针unique_ptr的用法

    unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...

随机推荐

  1. python webserver, based on SimpleHTTPServer

    #-*- coding:utf-8 -*- #author: lichmama #email: nextgodhand@163.com #filename: httpd.py import io im ...

  2. Dev控件学习-GridControl中的BandGridview导出多层行头操作

    BandGridview默认导出的是Columns的列头信息,而不是Bands的列头信息,为了实现导出多层行头.代码如下 public static void ExportExcel2(DevExpr ...

  3. easyui点击搜索的时候获取不要文本框里面的值的问题

    jsp的代码 <div id="tb"> <input id="AppID" placeholder="请根据申请人ID搜索&quo ...

  4. Asp.Net Core 中无法使用 ConfigurationManager.AppSettings

    刚刚接触.net core ,准备把之前的一些技术常用工具先移植到.net Standard上面来, 方便以后使用,结果用到ConfigurationManager 的 AppSettings 就出现 ...

  5. 列表操作之定义,切片(取元素)(Python)

    学完列表,元组,字典,集合以后,发现他们长的有些像,傻傻分不清,现在回顾下,以代码为例进行分析每一种操作的属性.(英语不佳,错误请忽略) 举栗如下:names = ["hbb",' ...

  6. Android - Fragment(二)加载Fragment

    Fragment加载方法 加载方法有两种,在xml文件中注册,或者是在Java代码中加载. xml中注册 例如在fragment_demo.xml中定义 <?xml version=" ...

  7. Docker初步了解

    Docker 是什么 https://www.docker.com/ Docker 这个单词英文原意是码头工人,搬运工的意思,这个搬运工搬运的是各种应用的容器. 官方的说法是,Docker 是提供给开 ...

  8. ES6函数扩展

    前面的话 函数是所有编程语言的重要组成部分,在ES6出现前,JS的函数语法一直没有太大的变化,从而遗留了很多问题和的做法,导致实现一些基本的功能经常要编写很多代码.ES6大力度地更新了函数特性,在ES ...

  9. Linux项目自动部署

    场景:linux中自动部署项目在工作中经常遇到,快速高效的部署项目能够大幅提高工作效率.现在将项目部署的过程记录下来,以供参考,其中用到的知识点现在还有很多不很清楚,后面要好好琢磨琢磨! 1 项目部署 ...

  10. bootstrap-table 怎么自定义搜索按钮实现点击按钮进行查询

    bootstrap-table自带搜索框感觉有点丑,我们可以把搜索功能单独拉出来放到页面的某一个位置. 首先我们看一下官方演示: 如果你感觉集成的检索框不太好看,而且我们也不想让搜索框和列表放到一块去 ...