首页 > 其他分享 >狂神说Go语言—指针与结构体

狂神说Go语言—指针与结构体

时间:2022-12-27 19:11:57浏览次数:34  
标签:p1 fmt Println Go 狂神 main ptr 指针

指针

GO语言中指针是很容易学习的,GO语言中使用指针可以更简单的执行一些任务。我们都知道,变量是一种使用方便的占位符,用手引用计算机内存地址。Go语言的取地址符是&,放到一个变量的使用就会返回相应变量的内存地址

指针的概念

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

变量是一种使用方便的占位符,用于引用计算机内存地址

一个指针变量指向了一个值的内存地址

a存地址, 0xc00001c0b8 值为10
b指针变量,指向内存地址	0xc00001c0b8
变量b持有a的地址,即b指向a
package main

import "fmt"

func main() {
   var a int = 10
   fmt.Println("a的值为:", a)
   fmt.Println("a的内存地址为:", &a)

   var b = &a //将a的内存地址赋值给b
   fmt.Println("b的值为:", b)
   fmt.Println("b指向a的值:", *b) //指针
   
   *b = 20
   fmt.Println("a的值为:", a)
}
/*
a的值为: 10
a的内存地址为: 0xc00001c0b8
b的值为: 0xc00001c0b8
b指向a的值: 10
*/

指针的使用

指针使用流程:

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

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

package main

import "fmt"

func main() {
   var a int = 10
   fmt.Println("a的值为:", a)
   fmt.Println("a的内存地址为:", &a)

   var p *int
   p = &a
   fmt.Println("p的值为:", p)
   fmt.Println("p取a的值为:", *p)
   fmt.Println("p自己的内存的地址为:", &p)

   *p = 20
   fmt.Println("a的值为:", a)
   fmt.Println("p取a的值为:", *p)

   a = 30
   fmt.Println("a的值为:", a)
   fmt.Println("p取a的值为:", *p)

   // 再定义一个指针变量ptr,来指向指针变量p
   var ptr **int //不好理解可以*int看成一个整体
   ptr = &p
   fmt.Println("ptr的值为:", ptr)
   fmt.Println("ptr取p的值为:", *ptr)
   fmt.Println("ptr的内存的地址为:", &ptr)
   fmt.Println("ptr取p的变量的值为:", **ptr)

   **ptr = 40
   fmt.Println("a的值为:", a)
   fmt.Println("p取a的值为:", *p)
   fmt.Println("ptr取p的变量的值为:", **ptr)
}
/*
a的值为: 10
a的内存地址为: 0xc0000a6058
p的值为: 0xc0000a6058
p取a的值为: 10
p自己的内存的地址为: 0xc0000ca020
a的值为: 20
p取a的值为: 20
a的值为: 30
p取a的值为: 30
ptr的值为: 0xc0000ca020
ptr取p的值为: 0xc0000a6058
ptr的内存的地址为: 0xc0000ca028
ptr取p的变量的值为: 30
a的值为: 40
p取a的值为: 40
ptr取p的变量的值为: 40
*/

指针与数组

数组指针:首先是一个指针,一个数组的地址

指针数组:它是一个数组,存储的数据类型是指针

package main

import "fmt"

func main() {
   //定义一个数组
   arr1 := [4]int{1, 2, 3, 4}
   fmt.Printf("arr1的内存地址:%p\n", &arr1)

   // 定义一个指针 指向数组
   var p1 *[4]int
   p1 = &arr1 //将arr1的地址赋值给指针p1
   fmt.Printf("p1->arr1的地址%p\n", p1)
   fmt.Printf("p1->自己的地址%p\n", &p1)
   fmt.Println("p1->a变量的值", *p1)

   (*p1)[0] = 100 //将数组第一个元素值改为100
   fmt.Println("p1->a变量的值", *p1)

   // 简化写法
   p1[0] = 200
   fmt.Println("p1->a变量的值", *p1)

   fmt.Println("================================")

   // 指针数组 先定义四个变量
   a := 1
   b := 2
   c := 3
   d := 4
   arr2 := [4]*int{&a, &b, &c, &d} //将四个变量的地址存放到数组
   fmt.Println(arr2)
   //*arr2取值  将第一个元素值更改为100
   *arr2[0] = 100
   //打印输出数组第一个元素也就是a的值
   fmt.Println(*arr2[0])
   //再次验证下a的值更改后是否相同
   fmt.Println(a)
}
/*
arr1的内存地址:0xc000012200
p1->arr1的地址0xc000012200
p1->自己的地址0xc00000a030
p1->a变量的值 [1 2 3 4]
p1->a变量的值 [100 2 3 4]
p1->a变量的值 [200 2 3 4]
================================
[0xc00001c0b8 0xc00001c0e0 0xc00001c0e8 0xc00001c0f0]
100
100
*/

指针函数

一个函数,该函数的返回值是一个指针

package main

import "fmt"

func main() {
   ptr := f1() //创建一个ptr接收f1函数传递过来的数组地址
   // 可以将传递过来的函数数组打印输出
   fmt.Printf("ptr->&arr1:%T\n", ptr)  //输出类型
   fmt.Println("ptr->arr1:", *ptr)     //arr1的数组
   fmt.Println("ptr->arr1->地址:", &ptr) //arr1的地址
   fmt.Println("输出第一个元素的值", (*ptr)[0])
   fmt.Println("简写后的第一个元素值", ptr[0])
}

// 定义一个函数 f1 返回值类型为指针
func f1() *[4]int {
   // 定义一个数组
   arr1 := [4]int{1, 2, 3, 4}
   return &arr1 //返回数组的地址
}
/*
ptr->&arr1:*[4]int
ptr->arr1: [1 2 3 4]
ptr->arr1->地址: 0xc00000a028
输出第一个元素的值 1
简写后的第一个元素值 1

*/

指针作为参数

package main

import "fmt"

func main() {
   a := 10
   fmt.Println("调用f2函数前a:", a)
   f2(&a)
   fmt.Println("调用f2函数后a:", a)
}
// 指针作为一个变量
// 定义一个f2的函数,传递进来的参数为指针
func f2(ptr2 *int) {
   fmt.Println("ptr2:", ptr2)
   fmt.Println("*ptr2:", *ptr2)
   *ptr2 = 100
}
/*
调用f2函数前a: 10
ptr2: 0xc00001c0b8
*ptr2: 10
调用f2函数后a: 100
*/

结构体

结构体是由一系列具有相同类型或不同类型的变量数据构成的数据集合我们一般用来封装一类事务的变量,结构体可以理解为一堆变量的集合,结构体表示一项记录,比如保存人的信息,每个人都有以下属性:

  • Name:名字
  • Age:年龄
  • Sex:性别

定义结构体

结构体定义需要使用type和struct语句

struct语句定义了一个新的数据类型,结构体中有一个或多个成员

type语句设定了结构体的名称

package main

import "fmt"

type User struct {
   name string //姓名
   age  int    //年龄
   sex  string //性别
}

func main() {
   var user1 User
   fmt.Println(user1) //{空 0 空}
   user1.name = "kuansghen"
   user1.age = 18
   user1.sex = "男"
   fmt.Println(user1)
   //也可以将信息单个提取出来
   fmt.Println(user1.name)
   fmt.Println(user1.age)

   // 快捷创建
   user2 := User{}
   user2.name = "feige"
   user2.age = 30
   user2.sex = "男"
   fmt.Println(user2)

   // 也可以直接在创建的时候进行赋值操作
   user3 := User{
      name: "dupeng",
      age:  22,
      sex:  "男",
   }
   fmt.Println(user3)

   // 顺序赋值
   user4 := User{"海摆摆", 20, "男"}
   fmt.Println(user4)
}
/*
{ 0 }
{kuansghen 18 男}
kuansghen
18
{feige 30 男}
{dupeng 22 男}
{海摆摆 20 男}
*/

结构体指针

结构体是值类型的

使用内置函数new()创建,new的所有Type都返回指针

user1:=new(Users)

package main

import "fmt"

type Users struct {
   name string
   age  int
   sex  string
}

func main() {
   user1 := Users{"kuangshen", 18, "男"}
   fmt.Println(user1) //赋值前打印输出
   user2 := user1     //将user1赋值给user2
   user2.name = "zhangsan"
   fmt.Println(user1) //赋值后输出
   //将传递后的对象重新赋值之后打印输出,结果为改变,由此得出结构体是值类型

   //指针
   var user3 *Users
   user3 = &user1
   fmt.Printf("%T\n", user3) //输出user3类型
   user3.name = "lisi"
   fmt.Println(user1)

   //通过new关键字创建也是引用类型
   user4 := new(Users)
   user4 = &user1 //也是可以通过取地址符方式,将user1引用到user4
   user4.name = "wangwu"
   user4.age = 20
   fmt.Printf("%T\n", user4) //输出user4类型
   fmt.Println(user1)

}
/*
{kuangshen 18 男}
{kuangshen 18 男}
*main.Users
{lisi 18 男}
*main.Users
{wangwu 20 男}
*/

匿名结构体

匿名结构体:没有名字的结构体

匿名字段:一个结构体的字段没有字段名

package main

import "fmt"

// 名称为Student的结构体
type Student struct {
   name string
   age  int
}
type Teacher struct {
   //匿名字段
   string
   int
}

func main() {
   s1 := Student{"kuangshen", 18}
   fmt.Println(s1)

   //匿名结构体
   s2 := struct {
      name string
      age  int
   }{"秦疆", 27}
   fmt.Println(s2)

   t1 := Teacher{"zhangsan", 3}
   fmt.Println(t1)
   //匿名字段 默认用字段数据类型当字段名称
   fmt.Println(t1.string)
   fmt.Println(t1.int)
}
/*
{kuangshen 18}
{秦疆 27}
{zhangsan 3}
zhangsan
3
*/

结构体嵌套

一个结构体可能包含一个字段,这个字段又是一个结构体,这被称为结构体嵌套

package main

import "fmt"

type Person struct {
   name    string
   age     int
   address Address //结构体嵌套
}
type Address struct {
   city, state string
}

func main() {
   var person = Person{}
   person.name = "kuangshen"
   person.age = 18
   person.address = Address{
      city:  "广州",
      state: "中国",
   }
   fmt.Println(person)
}
//{kuangshen 18 {广州 中国}}

结构体导出

如果结构体名称首字母小写,则结构体不会被导出。这时,即使结构体成员字段名首字母大写也不会导出

如果结构体首字母大写,则结构体有可能导出,只会导出大写首字母的成员字段,那些小写首字母的成员字段不会被导出

如果存在嵌套结构体,即使嵌套在内层的结构体名称首字母小写,外部也能访问到其中首字母大写的成员字段

这里自己出现一个小插曲,导包问题!

  • 直接在main方法中使用,系统会自动帮忙导入对应包,而自己手动导入,只要不使用就会消失
package main

import (
   "awesomeProject/pojo"
   "fmt"
)

func main() {
   var user pojo.User
   user.Name = "kuangshen"
   user.Money = 100
   fmt.Println(user)
}
//{kuangshen 0 100}

标签:p1,fmt,Println,Go,狂神,main,ptr,指针
From: https://www.cnblogs.com/DuPengBG/p/17008793.html

相关文章

  • Flutter 实现 “真” 3D 动画效果,用纯代码实现立体 Dash 和 3D Logo
    我正在参加「创意开发投稿大赛」详情请看:​​掘金创意开发大赛来了!​​本篇将给你带来更加炫酷动画效果,最后教你如何通过纯代码实现一只立体的Flutter的吉祥物Dash和3......
  • django 11 django中间件
    今日内容详细目录今日内容详细django中间件三个了解的方法基于django中间件实现功能的插拔式设计cookie与session简介django操作cookiedjango操作sessiondjango中间件三......
  • django 12 csrf跨站请求伪造
    今日内容详细目录今日内容详细csrf跨站请求伪造csrf校验策略csrf相关装饰器auth认证模块auth认证相关模块及操作扩展auth_user表csrf跨站请求伪造钓鱼网站:模仿一个正规......
  • Google VR技术大揭秘
    VR虚拟现实(VirtualReality)技术是一种可以创建和体验虚拟世界的计算机仿真系统,它利用计算机生成一种模拟环境,是一种多源信息融合的、交互式的三维动态视景和实体行为的系统......
  • What's new in dubbo-go-pixiu 0.5.1
    dubbo-go-pixiuv0.5.1(链接​​https://github.com/apache/dubbo-go-pixiu/releases/tag/v0.5.1-rc2​​)经过apache发版投票流程今天正式发版,在此感谢关注dubbo-go-p......
  • GO 使用嵌套map应该多次分配空间
    GO使用嵌套map应该多次分配空间demopackagemainimport( "fmt")funcmain(){ //初始化一个map vartmpmap[int64]interface{} //tmp[1]="abc"//pan......
  • GoLang初探
    简介     多核处理器越来越普及,那有没有一种简单的办法,能够让我们写的软件释放多核的威力?答案是:Yes。随着Golang,Erlang,Scale等为并发设计的程序语言的兴......
  • Android NDK下编译google protocol buffer(protobuf)
    前面发了一片windows下编译protobuf的文章后来把生成的.a文件加到android工程后发现不可用所以只好自己使用NDK编译protobuf了(虽然这样,生成的Inclule的头文件还是很有用......
  • 初步实现GoQtTemplate
    #ifndefMAINWINDOW_H#defineMAINWINDOW_H#include<QMainWindow>//新添加#include<opencv2/core/core.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/......
  • GO json.Unmarshal() 解析不区分json字段的大小写
    GOjson.Unmarshal()解析不区分json字段的大小写demopackagemainimport( "encoding/json" "fmt")typeDemostruct{ ABDstring`json:"ABD"`}typeDem......