Golang的高级数据类型-指针(Pointer)实战篇

摘要:
否则,将追究法律责任*//P2:=p+100}III。指针变量赋值packagemainimportfuncmain(){/**指针赋值有两种方法:1˃。将相同类型的变量的地址分配给指针;2˃。使用新函数请求一块内存空间并返回地址;*/varfmt.Printlnfmt.Println/**方案1:定义相同类型的一个变量,然后将地址分配给该指针变量。

          Golang的高级数据类型-指针(Pointer)实战篇

                               作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 

 

  前面分享过存储数据的方式,可以通过变量,或者复合类型中的数组,切片,Map,结构体等进行存储。今天我们来分享一下Go语言中的指针操作。

  

一.变量地址和指针

1>.定义指针变量

package main

import (
    "fmt"
)

func main() {
    /**
    在Go语言中,一旦定义了一个变量就会在内存中开辟空间。因此,在Go语言中为了避免空间的浪费,定义变量若未使用就会编译报错。
    */
    var age uint8 = 18
    /**
    我们可以使用取地址运算符("&")来获取数据的内存地址。
    %p:
        是一个占位符,表示输出一个十六进制地址格式。
    
:
        表示换行符。
    */
    fmt.Printf("age的值是:[%d],age的内存地址是:[%p]
", age, &age)

    /*
        接下来我们定义一个uint8类型的指针变量p1,其实指针变量也是变量,只不过指针变量指向了变量的内存地址。
    */
    var p1 *uint8

    /*
        对age变量取地址并将结果赋值给指针变量。
    */
    p1 = &age
    fmt.Println(p1)
}

Golang的高级数据类型-指针(Pointer)实战篇第1张

2>.数组和切片指针的区别

package main

import (
    "fmt"
)

func main() {
    //定义一个字符串数组
    var nameList [56]string
    fmt.Printf("nameLists数组的内存地址为%p
", &nameList)
    fmt.Printf("nameList数组中第一个元素的地址为%p
", &nameList[0])
    fmt.Printf("nameList数组中第二个元素的地址为%p
", &nameList[1])
    fmt.Printf("nameList数组中第三个元素的地址为%p

", &nameList[2])

    //定义一个整型数组
    var age_list [56]int
    fmt.Printf("age_list数组的内存地址为%p
", &age_list)
    fmt.Printf("age_list数组中第一个元素的地址为%p
", &age_list[0])
    fmt.Printf("age_list数组中第二个元素的地址为%p
", &age_list[1])
    fmt.Printf("age_list数组中第三个元素的地址为%p

", &age_list[2])

    //定义一个整型切片
    age_slice := make([]int, 56)
    /**
    age_slice切片变量保存的是存储切片容器的地址。他并不像数组那样直接指向数组的首元素地址,它类似于一个二级指针。
    当我们使用取地址运算符对age_slice变量取地址时并不是取的切片真正存储切片容器的地址,而是存储切片容器地址变量本身的地址哟~
    */
    fmt.Printf("age_slice切片变量本身的内存地址为%p
", &age_slice)

    /**
    通过下标访问第一个元素其实访问的是age_slice变量中保存的内存地址对应的下标。
    */
    fmt.Printf("age_slice切片中第一个元素的地址为%p
", &age_slice[0])
    fmt.Printf("age_slice切片中第二个元素的地址为%p
", &age_slice[1])
    fmt.Printf("age_slice切片中第三个元素的地址为%p

", &age_slice[2])
}

Golang的高级数据类型-指针(Pointer)实战篇第2张

二.指针的使用

1>.通过指针间接修改变量的值

package main

import (
    "fmt"
)

func main() {

    //使用自动推导类型创建一个age变量
    age := 18

    //我们将age变量的内存地址赋值给指针变量p1
    p1 := &age

    /**
    我们可以使用取值运算符("*")来获取指针变量的值。
    %p:
        是一个占位符,表示输出一个十六进制地址格式。
    %d:
        是一个占位符,表示输出一个整型。
    
:
        表示换行符。
    *:
        取值运算符,可以将指针变量中的保存的数据取出来。换句话说,可以将一段内存地址保存的值取出来。
    */
    fmt.Printf("age的内存地址是:%p,age的值是:%d
", p1, *p1)

    //我们可以通过指针间接修改变量的值
    *p1 = 27
    fmt.Printf("age的内存地址是:%p,age的值是:%d
", p1, age)
}

Golang的高级数据类型-指针(Pointer)实战篇第3张

2>.使用指针注意事项

package main

import (
    "fmt"
)

func main() {

    /**
    温馨提示:
        在使用指针变量时,要注意定义指针默认值为nil,如果直接擦欧总指向nil的内存地址会报错;
        在其它语言中,比如c++,指针是允许运算的,但是在Go语言中,指针只有取地址运算符和取值运算符,不允许指针参与运算哟~
    */
    var p *int

    /**
    错误代码:
        由于p指针变量默认值是nil,因此会报错"invalid memory address or nil pointer dereference"
    */
    //*p = 123

    age := 18
    p = &age //所以,在使用指针变量时,一定要让指针变量有正确的指向。
    fmt.Printf("age的内存地址是:%p,age的值是:%d
", p, *p)

    /**
    错误代码:
        在Go语言中,指针只有取地址运算符和取值运算符。
    */
    //p2 := p + 100
}

Golang的高级数据类型-指针(Pointer)实战篇第4张

三.指针变量赋值

package main

import (
    "fmt"
)

func main() {
    /**
    为指针赋值有两种方法:
        1>.把同类型的变量地址赋值给指针;
        2>.使用new函数,就是申请一片内存空间,返回地址;
    */
    var (
        p1 *int
        p2 *int
    )
    fmt.Println("p1的默认值是:", p1)
    fmt.Println("p2的默认值是:", p2)

    /**
    方案一:
        定义一个同类型的变量,然后取地址赋值给指针变量。
    */
    age := 18
    p1 = &age
    fmt.Printf("p1的内存地址是:%p,p1的值是:%d
", p1, *p1)

    /**
    方案二:
        使用new函数,比如"new(int)"表示创建一个int大小的内存空间,返回为*int
    */
    p2 = new(int)
    fmt.Printf("p2的内存地址是:%p,p2的值是:%d
", p2, *p2)
    *p2 = 2020 //为指针变量赋值
    fmt.Printf("p2的内存地址是:%p,p2的值是:%d
", p2, *p2)
}

Golang的高级数据类型-指针(Pointer)实战篇第5张

四.指针的应用场景(指针变量作为函数参数传递的时候是引用传递)

1>.交换两个变量的值案例

package main

import "fmt"

/*
    定义一个函数交换2个变量的值,接收的是2个int变量
*/
func swap(x int, y int) {
    x, y = y, x
}

/*
    定义一个函数交换2个变量的值,接收的是2个int指针变量
*/
func swapPointer(x *int, y *int) {
    *x, *y = *y, *x //需要改变的是地址上存储的内容
}

func main() {
    /*
        定义2个变量,一会用于在函数中交换两个变量的值
    */
    var (
        a = 100
        b = 200
    )

    /*
        值传递,不能通过函数内部修改影响外部变量。
    */
    swap(a, b)
    fmt.Printf("a = [%d], b = [%d]
", a, b)

    /*
        指针变量作为函数参数传递的时候是引用传递
    */
    swapPointer(&a, &b)
    fmt.Printf("a = [%d], b = [%d]
", a, b)
}

Golang的高级数据类型-指针(Pointer)实战篇第6张

2>.结构体传参案例

package main

import (
    "fmt"
)

type Student struct {
    Name string
    Age  int
}

func addAge(s Student) {
    s.Age += 1
}

/**
在实际开发中,一般传递的结构体对象都是指针传递
*/
func addAgePointer(s *Student) {
    s.Age += 2
}

func main() {

    s1 := Student{"Jason Yin", 18}
    addAge(s1)
    fmt.Printf("姓名:[%s],年龄[%d]
", s1.Name, s1.Age)
    /**
    结构体对象是值传递,但一般函数传递的都是结构体对象指针
    */
    addAgePointer(&s1)
    fmt.Printf("姓名:[%s],年龄[%d]
", s1.Name, s1.Age)
}

Golang的高级数据类型-指针(Pointer)实战篇第7张

 

免责声明:文章转载自《Golang的高级数据类型-指针(Pointer)实战篇》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇在workbench中导入.sql文件!(导入数据库文件)MongoDB无法启动的解决方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android智能指针sp wp详解

研究Android的时候,经常会遇到sp、wp的东西,网上一搜,原来是android封装了c++中对象回收机制。说明:1. 如果一个类想使用智能指针,那么必须满足下面两个条件:a. 该类是虚基类RefBase的子类或间接子类b. 该类必须定义虚构造函数。如virtual ~MyClass(); 2. 本文以类BBinder来进行说明,其余类使用sp或wp...

golang--解决邮件发送标题乱码问题

**一封最简单的邮件格式内容:** To: 123@qq.com CS: 1234@qq.com From: 1234@qq.com Subject: test 正文 邮件是和http类似的文本协议,由邮件头和邮件内容两部分组成,中间以空行分隔,邮件头每行对应一个字段,和http头类似,比如这里的To,CC,From,Subject,分别代表收件人...

Yii2基本概念之——配置(Configurations)

在Yii中创建新对象或者初始化已经存在的对象广泛的使用配置,配置通常包含被创建对象的类名和一组将要赋值给对象的属性的初始值,这里的属性是Yii2的属性。还可以在对象的事件上绑定事件处理器,或者将行为附加到对象上。从而在定义了对象的初始值的同时,充分规定对象的运行时的动态特性。 以下代码中的配置被用来创建并初始化一个数据库连接: $config = [...

基于无锁的C#并发队列实现

最近开始学习无锁编程,和传统的基于Lock的算法相比,无锁编程具有其独特的优点,Angel Lucifer的关于无锁编程一文对此有详细的描述。 无锁编程的目标是在不使用Lock的前提下保证并发过程中共享数据的一致性,其主要的实现基础是CAS操作,也就是compare_and_swap,通过处理器提供的指令,可以原子地更新共享数据,并同时监测其他线程的干...

golang-函数

查看生成的汇编代码go tool compile -S xx.go //编译器对汇编代码进行优化 go tool compile -S -N -l xx.go      //不优化 注:如果编译时不使用 -N -l 参数,编译器会对汇编代码进行优化,编译结果会有较大差别 c语言汇编分析 // ch04/my_function.cint my_functio...

linux下生成core dump文件方法及设置【转】

转自:https://blog.csdn.net/andy31688/article/details/84493251?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source...