golang:指针的三个概念以及new

指针

要明白指针,需要知道几个概念:指针地址、指针类型和指针取值

import "fmt"


func main() {
	var a int = 20;
	var ip *int

	ip = &a; // 将a的门牌号取出来放入ip中

	fmt.Printf("a变量的地址:%x\n" , &a) //a变量的地址:c042054080
	fmt.Printf("ip指针变量存储的是a变量的门牌号: %x\n", ip) //ip指针变量存储的是a变量的门牌号: c042054080
	fmt.Println("通过门牌号取相应内存取出值:", *ip) //通过门牌号取相应内存取出值: 20
}


认识指针地址和指针类型

一个指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。当一个指针被定义后没有分配到任何变量时,它的默认值是nil。指针变量通常缩写为ptr。

每个变量在运行时都有一个地址,这个地址表示变量在内存中的位置。Go语言中使用在变量名前面添加&操作符(前缀)来获取变量的内存地址(取地址操作),格式如下:

ptr := &v    // v 的类型为 T

其中 v 代表被取地址的变量,变量 v 的地址使用变量 ptr 进行接收,ptr 的类型为*T,称做 T 的指针类型,*代表指针。

package main
import (
    "fmt"
)
func main() {
    var cat int = 1
    var str string = "banana"
    fmt.Printf("%p %p", &cat, &str)
}

在这里插入图片描述

从指针获取指针指向的值

当使用&操作符对普通变量进行取地址操作并得到变量的指针后,可以对指针使用*操作符,也就是指针取值,代码如下。

package main

import "fmt"

func main() {
	// 准备一个字符串类型
	var house = "Malibu Point 10880, 90265"
	// 对字符串取地址, ptr类型为*string
	ptr := &house
	// 打印ptr的类型
	fmt.Printf("ptr type: %T\n", ptr)
	// 打印ptr的指针地址
	fmt.Printf("address: %p\n", ptr)
	// 对指针进行取值操作
	value := *ptr
	// 取值后的类型
	fmt.Printf("value type: %T\n", value)
	// 指针取值后就是指向变量的值
	fmt.Printf("value: %s\n", value)

}

在这里插入图片描述
取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。

变量、指针地址、指针变量、取地址、取值的相互关系和特性如下:

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

使用指针修改值

通过指针不仅可以取值,也可以修改值。

package main

import "fmt"

func main() {

	var house = "Malibu Point 10880, 90265"
	ptr := &house
	*ptr = "change";
	fmt.Printf("value: %s\n", *ptr)

}

在这里插入图片描述

创建指针的另一种方法——new() 函数

Go语言还提供了另外一种方法来创建指针变量,格式如下:

new(类型)

一般这样写:

str := new(string)
*str = "Go语言教程"
fmt.Println(*str)

new()函数可以创建一个对应类型的指针,创建过程会分配内存,被创建的指针指向默认值。

package main

import "fmt"

type name int8
type first struct {
	a int
	b bool //未初始化的变量自动赋上初始值
	name
}

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

	var vb = first{1, false, 2}
	fmt.Println(vb, vb.a, vb.b, vb.name) //{1 false 2} 1 false 2


	var ip *first = &vb;
	fmt.Println(&vb) // &{1 false 2}

	fmt.Println(*ip, (*ip).a, (*ip).b, (*ip).name) //{1 false 2} 1 false 2
	fmt.Println(ip, ip.a, ip.b, ip.name) //1 false 2

	// 取出ip的地址然后去访问值
	fmt.Println(*(&ip), *(&ip.a), *(&ip.b), *(&ip.name)) //&{1 false 2} 1 false 2
	// 取出ip的地址
	fmt.Println(&ip, &ip.a, &ip.b, &ip.name) //0xc042004030 0xc042008110 0xc042008118 0xc042008119
	fmt.Println(&vb, &vb.a, &vb.b, &vb.name) //&{1 false 2} 0xc042008110 0xc042008118 0xc042008119
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值