golang指针相关

news2024/10/6 1:41:05

指针相关的部分实在是没有搞太明白,抽时间来总结下。

1.指针相关基础知识
比如现在有一句话:『谜底666』,这句话在程序中一启动,就要加载到内存中,假如内存地址0x123456,然后我们可以将这句话复制给变量A,这句话的地址复制给变量B,首先变量B就是一个指针变量。
& 运算符:用于取地址
*运算符:用于根据地址取值
PS:地址是干嘛的:每个变量在运行是都有一个地址,这个地址代表该变量在内存中的位置

func main() {
	a := 10
	b := &a //取地址  等同于 var b *int = &a  此时的*int 代表变量b是一个*int类型
	fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078
	fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
	fmt.Println(&b)                    // 0xc00000e018 取b的地址(b本身也是一个指针类型)
}

放一张图:
在这里插入图片描述
对普通变量使用&操作符取地址的话,会得到这个变量的指针,然后可以用*操作符进行指针取值。

func main() {
	//指针取值
	a := 10
	b := &a // 取变量a的地址,将指针保存到b中
	fmt.Printf("type of b:%T\n", b)
	c := *b // 指针取值(根据指针去内存取值)
	fmt.Printf("type of c:%T\n", c)
	fmt.Printf("value of c:%v\n", c)
}
输出如下:
type of b:*int
type of c:int
value of c:10

再来个例子:

package main

import "fmt"

func main() {
	var (
		a int = 100
		b int = 300
	)
	fmt.Printf("交换前a的值: %d\n", a)
	fmt.Printf("交换前b的值: %d\n\n", b)

	swap(&a, &b)

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

func swap(x, y *int) {
	//值传递,两数交换
	*x, *y = *y, *x
}
//输出结果如下
交换前a的值: 100
交换前b的值: 300

交换后a的值: 300
交换后b的值: 100

小结:

  • 对变量进行取地址(&)操作,可以获得这个变量的指针变量。
  • 指针变量的值是指针地址。
  • 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。

2.如何进行指针传值

func modify1(x int) {
	x = 100
}
func modify2(x *int) {   //表示x是一个*int类型
	*x = 100   //对变量x取值后,赋值100,由于在主函数传的是变量a的地址,所以相当于对a赋值100
}
func main() {
	a := 10
	modify1(a)
	fmt.Println(a) // 10  不改变,
	modify2(&a)
	fmt.Println(a) // 100
}

上述代码也可以这样操作:

func modify3(x int) int{
    x = 100
    return x
}

func main() {
    a := 10
    a = modify3(a)  // 这里虽然都叫a,但是内存地址是不一样的
    fmt.Println(a) // 100
}

再来一个栗子:

func main() {
	a := 10
	pointerDemo03(&a)
	fmt.Println(a)
}

// 注意,指针作为函数的时候,参数也要加上*
func pointerDemo03(a *int) {
	*a = 20
}
//到现在位置应该明白了,不用再赘述这个了

3.new(不太在实际项目中见到)
使用new函数得到的是一个类型的指针,并且该指针对应的值为该类型的零值,每次调用 new 函数都会返回唯一的地址变量(当定义一个空 struct 时,通过 new 创建一个变量时,返回的地址是相同的。):

func main() {
	a := new(int)
	b := new(bool)
	fmt.Printf("%T\n", a) // *int
	fmt.Printf("%T\n", b) // *bool
	fmt.Println(*a)       // 0
	fmt.Println(*b)       // false
}

关于new函数再举一个栗子:

func main() {
    // 创建一个未命名的 int 类型变量,初始值是 0,返回值 p 是指向 int 类型变量的指针。
    p := new(int)
    fmt.Println(p, *p) // 0xc00001c0b8 0
    // 创建一个未命名的 string 类型变量,初始值是 "", 返回值是 q 是指向 string 类型变量的指针。
    q := new(string)
    fmt.Println(q, *q) // 0xc000010240 ""

    *q = "a"
    fmt.Println(*q) // a
}

make
make也是用于内存分配的,区别于new,它只用于slice、map以及chan的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了

4.数组指针与指针数组
指针数组是指元素为指针类型的数组,数组指针是获取数组变量的地址
数组指针:

func pointerDemo05() {
	arr := [10]int{1, 2, 3, 3, 4, 5}
	var p *[10]int  //定义p是一个数组指针
	p = &arr        //对这个数组指针赋值,赋值的是变量arr的地址
	fmt.Println(*p)      // 获取数组中的全部数据
	fmt.Println((*p)[0]) // 获取指定数组中索引的数据,因为*p是先运算,所以要先加括号,否则编译报错
	fmt.Println(p[0])    // 获取指定数组中索引的数据,这个格式和加括号一样,但是简化的写法

	for i := 0; i < len(p); i++ {
		fmt.Print(p[i], ",")
	}
}

指针数组:元素为指针类型的数组

func pointerDemo07() {
	var p [2]*int //注意和上面的区别
	a := 10
	b := 20
	// 变量a的内存地址保存在指针数组p的0索引,b保存在1索引
	p[0] = &a
	p[1] = &b
	fmt.Println(p)            // 获取p数组中的内存地址
	fmt.Println(*p[0], *p[1]) // 获取p数组中的指定索引数据

	for i := 0; i < len(p); i++ {
		fmt.Println(*p[i]) // 获取p数组中的所有的数据
	}

	for key, value := range p {
		fmt.Println(key, *value)
	}
}

5.结构体指针
直接使用结构体的方式(用new):

type People struct{
    Name string
    Age int
}

peo := new(People)
//因为结构体本质是值类型,所以创建结构体指针时已经开辟了内存空间
fmt.Println(peo == nil) //输出:false
//由于结构体中属性并不是指针类型,所以可以直接调用
peo.Name = "jeff"
fmt.Println(peo)//输出:&{jeff 0}
peo1:=peo
peo1.Name="高级语言"
fmt.Println(peo1,peo)//输出:&{高级语言 0} &{高级语言 0}

也可以声明结构体指针来进行赋值:

//声明结构体指针
var peo *People   //表示变量peo是一个*People类型(结构体指针类型)
//给结构体指针赋值
peo = &People{"jeff", 18}
/*
上面代码使用短变量方式如下
peo:= &People{"jeff", 18}
 */
fmt.Println(peo)

结构体指针比较的是地址,*结构体指针取出地址中对应的值

p1 := People{"jeff", 18}
p2 := People{"jeff", 18}
fmt.Printf("%p %p\n", &p1, &p2) //输出地址不同
fmt.Println(p1 == p2)           //输出:true

p3 := new(People)
p3 = &People{"jeff", 18}
//结构体变量不能和指针比较,使用*指针取出地址中值
fmt.Println(p1 == *p3) //输出:true

p4 := &People{"jeff", 18}
//指针比较的是地址
fmt.Println(p3 == p4) //输出:false

PS:使用new来初始化结构体后,得到的是结构体的地址,栗子如上
再来一个栗子:

type Student struct {
	// 成员名称不加var关键字
	id   int
	name string
	age  int
	addr string
}
func main() {
	stu := Student{001, "itzhuzhu", 23, "广州"}
	var p *Student
	p = &stu
	pointerDemo10(p)
	fmt.Println(stu)
}

func pointerDemo10(p *Student) {
	p.addr = "深圳"
}
//输出结果为{1 itzhuzhu 23 深圳}

下面这个同上面:

func main() {
	stu := Student{001, "itzhuzhu", 23, "广州"}
	//var p *Student
	//p = &stu
	pointerDemo10(&stu)
	fmt.Println(stu)
}

func pointerDemo10(p *Student) {
	p.addr = "深圳"
}

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

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

相关文章

什么是服务架构?微服务架构的优势又是什么?

文章目录1.1 单体架构1.2 分布式架构1.3 微服务架构1.4 单体架构和分布式架构的区分1.4 服务架构的优劣点1.4.1 单体架构1.4.2 分布式架构1.4.3 微服务架构1.5 总结1.1 单体架构 单体架构&#xff08;Monolithic Architecture&#xff09;是一种传统的软件架构&#xff0c;它将…

算法学习day56

算法学习day561.力扣583. 两个字符串的删除操作1.1 题目描述1.2分析1.3 代码2.力扣72. 编辑距离2.1 题目描述2.2 分析2.3 代码3.参考资料1.力扣583. 两个字符串的删除操作 1.1 题目描述 题目描述&#xff1a; 给定两个单词word1和word2&#xff0c;找到使得word1和word2相同…

探索数据结构之精髓:单链表解密

文章目录1. 前言2. 单链表的特点3. 单链表的基础操作&#x1f351; 接口总览&#x1f351; 初始化操作&#x1f351; 插入操作&#x1f345; 优化操作&#x1f351; 删除操作&#x1f345; 优化操作&#x1f351; 获取元素&#x1f345; 按置查找&#x1f345; 按值查找&#x…

从C出发 20 --- 函数参数深度剖析

我们在编写这个函数的时候参数 n 的值具体是多少&#xff1f; 在编写一个函数的时候参数值是没法确定的&#xff0c;所以将 (int n) 这个参数命名为形参 那么这个参数的值什么时候指定&#xff0c;具体函数调用的时候指定 比如 在main 里面调用 实参用来初始化形参 初始化之…

安装多个版本的Node.js的方法

要在同一台计算机上安装多个版本的Node.js&#xff0c;可以使用以下几种方法&#xff1a; 使用nvm&#xff08;Node Version Manager&#xff09;&#xff1a;nvm是一个用于管理多个Active Node.js版本的工具。您可以使用nvm轻松地在系统中安装、卸载和切换不同版本的Node.js。…

Leetcode每日一题——“消失的数字”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰又开新专栏了&#xff0c;以后会在Leetcode上面进行刷题&#xff0c;尽量每天写一道&#xff0c;请大家监督我&#xff01;&#xff01;&#xff01;好啦&#xff0c;让我们进入Leetcode的世界吧 力扣 对于这道题目&a…

南卡OE Pro上线!开放式耳机新里程碑!前所未有的音质舒适双冠

当前耳机市场放眼望去几乎都是TWS的天下&#xff0c;但是大多数的蓝牙耳机都存在着以下痛点&#xff1a;长时间佩戴涨耳、出现听诊器效应、耳朵内部发痒以及与外界声音隔开缺乏安全性等等问题。 为此&#xff0c;国内智能声学品牌厂商NANK南卡针对用户的特点&#xff0c;于近日…

中小企业如何实施知识管理策略?

随着信息化建设的深入&#xff0c;IT不仅成为企业运营的基础平台&#xff0c;而且在ERP、CRM、OA等信息系统内沉淀了大量的知识&#xff0c;成为企业创新的源泉&#xff0c;大中企业信息化建设中知识管理越来越重要。 应该如何实现知识管理呢&#xff1f; 知识管理本身就属于企…

Flutter系列(七)ListView 图文列表详解

完整工程&#xff1a; Flutter系列&#xff08;四&#xff09;底部导航顶部导航图文列表完整代码_摸金青年v的博客-CSDN博客 详细解读: Flutter系列&#xff08;五&#xff09;底部导航详解_摸金青年v的博客-CSDN博客 Flutter系列&#xff08;六&#xff09;顶部导航详解_摸金青…

初学SSM时做的-IKUN图书管理系统

项目介绍 项目工具:IntelliJ IDEA 2021.2.2 图书后台管理系统&#xff0c;采用SpringBootMybatiusThymeleaf&#xff0c;页面使用Element框架&#xff0c;使用RESTful API风格编写接口。 数据库使用mysql 已实现功能 基本增删改查,联表查询 拦截器登录验证 项目技术栈 Spr…

4.15--设计模式之创建型之责任链模式(总复习版本)---脚踏实地,一步一个脚印

一、什么是责任链模式&#xff1a; 责任链模式属于行为型模式&#xff0c;是为请求创建了一个接收者对象的链&#xff0c;将链中每一个节点看作是一个对象&#xff0c;每个节点处理的请求均不同&#xff0c;且内部自动维护一个下一节点对象。 当一个请求从链式的首端发出时&a…

C++(Qt)软件调试---qmake编译优化和生成调试信息(9)

C(Qt)软件调试—qmake编译优化和生成调试信息&#xff08;9&#xff09; 文章目录C(Qt)软件调试---qmake编译优化和生成调试信息&#xff08;9&#xff09;1、前言1.1 编译器优化是什么1.2 调试信息是什么1.3 测试环境2、Qt编译模式说明3、比较Linux下Qt三种编译模式1.1 编译生…

DevOps系列文章 - K8S知识体系

环境搭建部分&#xff1a; 1、安装前的准备工作 # 关闭防火墙 systemctl stop firewalld systemctl disable firewalld# 查看hostname并修改hostname # 查看本机hostname hostnamectl set-hostname k8s-master # 把本机名设置成k8s-master hostnamectl status # 查看修改结…

Linux复习 / 文件系统QA梳理

文章目录前言Q&A文件的基本理解Q&#xff1a;谈谈你是怎么理解文件的&#xff1f;Q&#xff1a;什么是当前工作路径&#xff1f;Q&#xff1a;文件与操作系统有着怎样的关系&#xff1f;Q&#xff1a;为什么语言要封装系统接口&#xff1f;文件描述符Q&#xff1a;系统和进…

基于JSP的网上购物系统的设计与实现(论文+源码)_kaic

摘 要 近些年来&#xff0c;社会的生产力和科技水平在不断提高&#xff0c;互联网技术也在不断更新升级&#xff0c;网络在人们的日常生活中扮演着一个重要角色&#xff0c;它极大地方便了人们的生活。为了让人们实现不用出门就能逛街购物&#xff0c;网络购物逐渐兴起慢慢变得…

ES6(声名、解构)

参考文档&#xff1a; ES6 入门教程https://es6.ruanyifeng.com/ 注意&#xff1a;内容较多&#xff1a;只看引用部分的内容即可&#xff08;代码一眼过搭配理解&#xff09; 一、变量声明 1. let let声名的变量只在所处于的块级有效 let a 10; if (true) {let b 20;cons…

人工智能 AI 绘画发展史

到了去年4月, 著名人工智能团队OpenAI 也发布了新模型 DALLE 2代&#xff0c;该名称来源于著名画家达利&#xff08;Dal&#xff09;和机器人总动员&#xff08;Wall-E&#xff09;, 同样支持从文本描述生成效果良好的图像. 而很多读者对AI绘画开始产生特别的关注, 或许是从以下…

有趣的Hack-A-Sat黑掉卫星挑战赛——AES加密通信链路侧信道攻击leaky

国家太空安全是国家安全在空间领域的表现。随着太空技术在政治、经济、军事、文化等各个领域的应用不断增加&#xff0c;太空已经成为国家赖以生存与发展的命脉之一&#xff0c;凝聚着巨大的国家利益&#xff0c;太空安全的重要性日益凸显[1]。而在信息化时代&#xff0c;太空安…

如何将Springboot项目通过IDEA打包成jar包,并且转换成可执行文件

首先在IDEA打开你的项目&#xff0c;需要确认项目可以正常运行&#xff0c;然后点击页面右侧的Maven,运行Lifecycle下的package, 此时在项目的target目录下就可以看到一个jar包 这个时候你可以在jar包所在目录下执行cmd窗口&#xff0c;运行 java -jar campus-market-0.0.1-S…

BUUCTF-SimpleRev

下载文件 查壳 没有加壳 并且是64 放入ida64 SHIFTF12 访问字符串 得到关键字符串 双击 然后 CRTLX 查找交互 F5 反编译 得到了代码 开始代码审计 我们可以发现有两个十六进制的东西 r 对其转换为字符串 srcSLCDN v9wodah 然后继续往下看 发现textjoin函数 我们进入看…