指针
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