十四、go语言的指针

news2024/11/25 14:40:16

一、指针

1.1 指针的概念

指针是存储另一个变量的内存地址的变量。

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

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

在这里插入图片描述

在上面的图中,变量b的值为156,存储在内存地址0x1040a124。变量a持有b的地址,现在a被认为指向b。

1.2 获取变量的地址

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

package main

import "fmt"

func main() {
   var a int = 10   

   fmt.Printf("变量的地址: %x\n", &a  )
}

运行结果:

变量的地址: 20818a220

1.3 声明指针

声明指针,*T是指针变量的类型,它指向T类型的值。

var var_name *var-type

var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。

var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮点型 */

示例代码:

package main

import "fmt"

func main() {
   var a int= 20   /* 声明实际变量 */
   var ip *int        /* 声明指针变量 */

   ip = &a  /* 指针变量的存储地址 */

   fmt.Printf("a 变量的地址是: %x\n", &a  )

   /* 指针变量的存储地址 */
   fmt.Printf("ip 变量的存储地址: %x\n", ip )

   /* 使用指针访问值 */
   fmt.Printf("*ip 变量的值: %d\n", *ip )
}

运行结果:

a 变量的地址是: 20818a220
ip 变量的存储地址: 20818a220
*ip 变量的值: 20

示例代码:

package main

import "fmt"

type name int8
type first struct {
	a int
	b bool
	name
}

func main() {
	a := new(first)
	a.a = 1
	a.name = 11
	fmt.Println(a.b, a.a, a.name)
}

运行结果:

false 1 11

未初始化的变量自动赋上初始值

package main

import "fmt"

type name int8
type first struct {
	a int
	b bool
	name
}

func main() {
	var a = first{1, false, 2}
	var b *first = &a
	fmt.Println(a.b, a.a, a.name, &a, b.a, &b, (*b).a)
}

运行结果:

false 1 2 &{1 false 2} 1 0xc042068018 1

获取指针地址在指针变量前加&的方式

1.4 空指针

Go 空指针
当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。
一个指针变量通常缩写为 ptr。

空指针判断:

if(ptr != nil)     /* ptr 不是空指针 */
if(ptr == nil)    /* ptr 是空指针 */

1.5 获取指针的值

获取一个指针意味着访问指针指向的变量的值。语法是:*a

示例代码:

package main  
import (  
    "fmt"
)

func main() {  
    b := 255
    a := &b
    fmt.Println("address of b is", a)
    fmt.Println("value of b is", *a)
}

1.6 操作指针改变变量的数值

示例代码:

package main

import (  
    "fmt"
)

func main() {  
    b := 255
    a := &b
    fmt.Println("address of b is", a)
    fmt.Println("value of b is", *a)
    *a++
    fmt.Println("new value of b is", b)
}

运行结果

address of b is 0x1040a124  
value of b is 255  
new value of b is 256  

1.7 使用指针传递函数的参数

示例代码

package main

import (  
    "fmt"
)

func change(val *int) {  
    *val = 55
}
func main() {  
    a := 58
    fmt.Println("value of a before function call is",a)
    b := &a
    change(b)
    fmt.Println("value of a after function call is", a)
}

运行结果

value of a before function call is 58  
value of a after function call is 55  

不要将一个指向数组的指针传递给函数。使用切片。

假设我们想对函数内的数组进行一些修改,并且对调用者可以看到函数内的数组所做的更改。一种方法是将一个指向数组的指针传递给函数。

package main

import (  
    "fmt"
)

func modify(arr *[3]int) {  
    (*arr)[0] = 90
}

func main() {  
    a := [3]int{89, 90, 91}
    modify(&a)
    fmt.Println(a)
}

运行结果

[90 90 91]

示例代码:

package main

import (  
    "fmt"
)

func modify(arr *[3]int) {  
    arr[0] = 90
}

func main() {  
    a := [3]int{89, 90, 91}
    modify(&a)
    fmt.Println(a)
}

运行结果

[90 90 91]

虽然将指针传递给一个数组作为函数的参数并对其进行修改,但这并不是实现这一目标的惯用方法。我们有切片。

示例代码:

package main

import (  
    "fmt"
)

func modify(sls []int) {  
    sls[0] = 90
}

func main() {  
    a := [3]int{89, 90, 91}
    modify(a[:])
    fmt.Println(a)
}

运行结果:

[90 90 91]

Go不支持指针算法。

package main

func main() {
b := […]int{109, 110, 111}
p := &b
p++
}

nvalid operation: p++ (non-numeric type *[3]int)

指针数组

package main

import "fmt"

const MAX int = 3

func main() {

   a := []int{10,100,200}
   var i int

   for i = 0; i < MAX; i++ {
      fmt.Printf("a[%d] = %d\n", i, a[i] )
   }
}

结果

a[0] = 10
a[1] = 100
a[2] = 200

有一种情况,我们可能需要保存数组,这样我们就需要使用到指针。

package main

import "fmt"

const MAX int = 3

func main() {
   a := []int{10,100,200}
   var i int
   var ptr [MAX]*int;

   for  i = 0; i < MAX; i++ {
      ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
   }

   for  i = 0; i < MAX; i++ {
      fmt.Printf("a[%d] = %d\n", i,*ptr[i] )
   }
}

结果

a[0] = 10
a[1] = 100
a[2] = 200

1.8 指针的指针

指针的指针

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

var ptr **int;
package main

import "fmt"

func main() {

   var a int
   var ptr *int
   var pptr **int

   a = 3000

   /* 指针 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 = 3000
指针变量 *ptr = 3000
指向指针的指针变量 **pptr = 3000

指针作为函数参数

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/684703.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

怎么输入文字生成绘画图?分享一份文字生成绘画教程

你是否曾经幻想过&#xff0c;将文字化为绘画&#xff0c;将思维转化为图像&#xff0c;让你的想象力得到更好的释放与表达&#xff1f;现在&#xff0c;这一切都变得可能了&#xff01;通过一些绘画软件&#xff0c;你可以轻松生成各种风格的绘画图。只需要一个创意的想法和一…

Selenium教程__POM架构(17)

POM是Page Object Model的简称&#xff0c;它是一种设计思想&#xff0c;意思是&#xff0c;把每一个页面&#xff0c;当做一个对象&#xff0c;页面的元素和元素之间操作方法就是页面对象的属性和行为。 POM一般使用三层架构&#xff0c;分别为&#xff1a;基础封装层、页面对…

SkyWalking--traceId的作用

原文网址&#xff1a;SkyWalking--traceId的作用_IT利刃出鞘的博客-CSDN博客 简介 本文介绍SkyWalking中traceId的作用。 traceId是什么 SkyWalking的一个核心功能就是&#xff1a;链路追踪。链路追踪就是跟踪一个请求的所有链路&#xff0c;而这个链路都是通过一个id来串起…

数据结构--算法空间复杂度

数据结构–算法空间复杂度 只需关注存储空间大小与问题规模相关的变量 计算规则与算法的时间复杂度类似 eg&#xff1a; S ( n ) O ( n 2 ) O ( n ) O ( 1 ) O ( n 2 ) S(n) O(n^2)O(n)O(1) O(n^2) S(n)O(n2)O(n)O(1)O(n2) 知识点回顾 & 重要考点

java list集合数据去重方式

1.概述 最近又是一轮代码review , 发现了一些实现去重的代码&#xff0c;在使用 list.contain … 我沉思&#xff0c;是不是其实很多初学者也存在这种去重使用问题&#xff1f; 所以我选择把这个事情整出来&#xff0c;分享一下。 2.contain 去重 首先是造出一个 List 模拟…

[CKA]考试之七层负载均衡Ingress

由于最新的CKA考试改版&#xff0c;不允许存储书签&#xff0c;本博客致力怎么一步步从官网把答案找到&#xff0c;如何修改把题做对&#xff0c;下面开始我们的 CKA之旅 题目为&#xff1a; Task 如下创建一个新的nginx Ingress资源&#xff1a; 名称: pong Namespace: i…

掌握这些容易被忽略的Vue细节,轻松排查问题,省时省力!

v-bind 绑定的值是 null 或者 undefined v-bind 如果绑定的值是 null 或者 undefined&#xff0c;那么该 attribute 将会从渲染的元素上移除。 当attribute 为布尔型时&#xff0c; 行为略有不同。 <button :disabled"isButtonDisabled">Button</button&…

CSS之平面转换

简介 作用&#xff1a;为元素添加动态效果&#xff0c;一般与过渡配合使用 概念&#xff1a;改变盒子在平面内的形态&#xff08;位移、旋转、缩放、倾斜&#xff09; 平面转换也叫 2D 转换&#xff0c;属性是 transform 平移 transform: translate(X轴移动距离, Y轴移动距…

@Valid接口参数校验怎么做,详细教程

接口参数校验教程 一、在字段上可以使用这个注解来设置校验 Null&#xff1a;被注释的元素必须为null NotNull&#xff1a;被注释的元素不能为null AssertTrue&#xff1a;该字段只能为true AssertFalse&#xff1a;该字段的值只能为false Min("value","messa…

机器学习:监督学习

目前&#xff0c;在机器学习系统中&#xff0c;监督学习&#xff08;Supervised Learning&#xff09;占主导地位。由于监督学习的任务定义明确&#xff0c;例如识别垃圾邮件或预测降水&#xff0c;因此它比无监督学习具有更多潜在用例&#xff1b;而与强化学习相比&#xff0c…

剑指offer(C++)-JZ51:数组中的逆序对(算法-排序)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 在数组中的两个数字&#xff0c;如果前面一个数字大于后面的数字&#xff0c;则这两个数字组成一个逆序对…

Java IO 学习总结(四)BufferedReader 缓冲字符流

Java IO 学习总结&#xff08;一&#xff09;输入流/输出流 Java IO 学习总结&#xff08;二&#xff09;File 类 Java IO 学习总结&#xff08;三&#xff09;BufferedInputStream Java IO 学习总结&#xff08;四&#xff09;BufferedReader 缓冲字符流 前言&#xff1a; 学…

Kibana介绍安装

目录 Kibana入门配置和安装启动数据探索Metricbeat仪表盘Nginx指标仪表盘【Metricbeat】Nginx日志仪表盘查看集群数据 Kibana入门 Kibana 是一款开源的数据分析和可视化平台&#xff0c;它是 Elastic Stack 成员之一&#xff0c;设计用于和 Elasticsearch 协作。可以使用 Kiban…

2023上半年软考系统分析师科目一整理-03

2023上半年软考系统分析师科目一整理-03 1. 嵌入式 1. 嵌入式 嵌入式系统已被广泛应用到各行各业。嵌入式系统是一个内置于设备中&#xff0c;对设备的各种传感器进行管理与控制的系统。通常&#xff0c;根据系统对时间的敏感程度可将嵌入式系统划分为( A )两种&#xff0c;而…

netwox构建IP协议数据包【网络工程】(保姆级图文)

目录 netwox构建IP协议数据包1) 不指定选项&#xff0c;直接运行该模块。执行命令如下&#xff1a;2) 指定源 IP 地址为 192.168.43.95&#xff0c;目标 IP 地址为 192.168.43.97。执行命令如下&#xff1a;3) 通过抓包&#xff0c;验证构造的 IP 数据包。捕获到的数据包如图所…

管理类联考——英语——趣味篇——不择手段——b开头单词

第一部分 核心词汇趣讲 Unit 2 boom n./v.&#xff08;发出&#xff09;隆隆声&#xff1b;激增&#xff0c;繁荣 loom想象成&#xff1a;一百(100)米(m)外有个妹妹(m也可以想象成妹妹)&#xff0c;你能看得清她吗?→&#xff08;模糊之物)耸现。 boom&#xff1a;六百个妹…

低代码可视化拖拽编辑器实现方案

一、前言 随着业务不断发展&#xff0c;低代码、无代码平台越来越常见&#xff0c;它降低开发门槛、快速响应业务需求、提升开发效率。零开发经验的业务人员通过可视化拖拽等方式&#xff0c;即可快速搭建各种应用。本文主要是讲解低代码可视化拖拽平台前端展示层面的实现逻辑…

@Async使用什么线程池?

文章目录 前言一、前言1、ThreadPoolTaskExecutor2、SimpleAsyncTaskExecutor3、测试代码 二、各种情况模拟1、未配置线程池2、配置异步线程池3、配置1个或多个非异步线程池4、同时配置异步和非异步线程池 三、总结 前言 本文的目的&#xff0c;主要是看到网上各种说辞&#x…

JVM-类加载与运行区详细分析(一)

目录 一、为什么会有类加载机制 二、类加载机制原理是什么 1、什么是类加载器&#xff1a;宏观 2、类加载器工作原理 1、装载 2、链接 3、初始化 3、何为装载的机制&#xff1a;微观 4、上面既然我们已经知道了啥是双亲委派了&#xff0c;那么怎么去破坏呢&#xff1f;…

【设计模式】工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式)详记

注&#xff1a;本文仅供学习参考&#xff0c;如有错漏还请指正&#xff01; 参考文献/文章地址&#xff1a; https://zh.wikipedia.org/wiki/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%EF%BC%9A%E5%8F%AF%E5%A4%8D%E7%94%A8%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E8%BD%AF%E4%BB%B…