go结构体指针

package main

import (
	"fmt"
)


type User struct{
	Username string
	Sex string
	Age int
	AvatarUrl string
}

func initUser1() {
	var user *User	
	fmt.Printf("user=%#v\n",user)  // user=(*main.User)(nil)  指针没有初始化是nil

	var user01 *User = &User{}
	user01.Age = 19  // 指针类型 实际是这样的,(*user01).Age  go做了一个语法糖,把(*user01).Age 简写成user01.Age
	user01.Username = "user01"
	(*user01).Sex = "女"
	// user01.Age = 19
	fmt.Printf("initUser1 user01=%#v\n",user01)
	fmt.Printf("user01.username=%s age=%d sex=%s avatar=%s\n",user01.Username,user01.Age,user01.Sex,user01.AvatarUrl)
	
	var user02 *User = &User{
		Username :"user02",
		Age :20,
	}
	fmt.Printf("user02=%#v\n",user02) 
	fmt.Printf("user02.username=%s age=%d sex=%s avatar=%s\n",user02.Username,user02.Age,user02.Sex,user02.AvatarUrl)

	var user03 *User = new(User)  //指针类型的必须要初始化分配内存才行 用new或者&User
	user03.Username = "user03"
	user03.Age = 19
	fmt.Printf("user03=%#v\n",user03) 
	fmt.Printf("user03.username=%s age=%d sex=%s avatar=%s\n",user03.Username,user03.Age,user03.Sex,user03.AvatarUrl)
}


func main() {
	initUser1()


}

输出:

user=(*main.User)(nil)
initUser1 user01=&main.User{Username:"user01", Sex:"女", Age:19, AvatarUrl:""}
user01.username=user01 age=19 sex=女 avatar=
user02=&main.User{Username:"user02", Sex:"", Age:20, AvatarUrl:""}
user02.username=user02 age=20 sex= avatar=
user03=&main.User{Username:"user03", Sex:"", Age:19, AvatarUrl:""}
user03.username=user03 age=19 sex= avatar=

package main

import (
	"fmt"
	"unsafe"
)


type Person struct{
	name string
	sex byte
	age int
}

func testStruct(){
	// 1.顺序初始化,必须全部初始化完整
	var man Person = Person{ name: "andy",sex: 'm', age: 18}
	fmt.Println(  "man:", man)

	// 2.部分初始化
	man2 := Person{sex:'f', age :19}
	fmt.Println( " man2: ", man2)
	//索引成员变量“.”
	fmt.Printf( "man2.name = %q\n", man2.name)

	var man3 Person
	man3.name = "mike"
	man3.sex = 'm'
	man3.age = 99
	fmt.Println(  "man3 : ", man3)
	man3.age = 1073
	fmt.Println(  "man3 : ", man3)

}

func compareStruct(){
	//结构体比较
	var p1 Person = Person{name: "andy", sex: 'm', age: 18}
	var p2 Person = Person{ name: "andy", sex: 'm', age: 18}
	var p3 Person = Person { name: "andy", sex: 'm', age: 181}
	fmt.Println( "p1 == p2 ?", p1 == p2)
	fmt.Println("p1 == p3 ?", p1 == p3)

}

func passValueStruct(man Person) {
	fmt.Println(  "002 passValueStruct temp size:", unsafe.Sizeof(man))
	man.name = "name1"
	man.age = 33
	fmt.Println( "01test: man", man)
	fmt.Println(  "003  temp size:", unsafe.Sizeof(man))
}

func pointStruct(){
	var p1 *Person = &Person { name: "n1",sex: 'f', age: 19}
	fmt.Println( "p1", p1)

	var p2 = new(Person)
	p2 = &Person { name: "n2",sex: 'f', age: 20}
	fmt.Println("p2",p2)

	var tmp = Person{ name: "n3",sex: 'f', age: 21}
	var p3  *Person
	p3 = &tmp
	fmt.Println("p3",p3)

	var p4 = new(Person)
	p4.name = "n4"
	p4.age = 22
	p4.sex = 'f'
	fmt.Println("p4",p4)

	//结构体指针变量的地址==结构体首个元素的地址.
	fmt.Printf(  "p3 = %p \n", p3)
	fmt.Printf( "&p3.name = %p \n", &p3.name)
}
func test2(p *Person){
	fmt.Println( "test2:", unsafe.Sizeof(p))
	p.name = "Luffy"
	p. age = 779
	p.sex = 'm'
}

func initStruct(){
	var temp =Person{}
	fmt.Println(  "main temp size:", unsafe.Sizeof(temp))
	fmt.Println(  "00temp", temp)
	passValueStruct(temp) //值传递。将实参的值拷贝一份给形参。
	fmt.Println(  "02temp", temp)


	//结构体变量的地址==结构体首个元素的地址。
	fmt.Printf( "&tmp = %p \n", &temp)
	fmt.Printf( "&temp.name = %p \n", &temp.name)

	//unSafe.Sizeof(变量名) ——>此种类型的变量所占用的内存空间大小
	fmt.Println(  " main temp size:", unsafe.Sizeof(  true))
}



func swapTest(){
	/*结构体指针传参:
	unSafe.Sizeof(指针)︰不管何种类型的指针,在64位操作系统下,大小一致。均为8字节!!!
		将结构体变量地址值,传递(传引用)。  —— 使用频率非常高! ! !*/
	p3 := new(Person)
	p3.name = "n3"
	p3.age = 22
	p3.sex = 'f'
	fmt.Printf( "p3, type= %T\n", p3)
	fmt.Println(  "p3:", p3)
	fmt.Println( "main:", unsafe.Sizeof(p3))
	test2(p3)
	fmt.Println(  "p3:", p3)

}

func main(){
	testStruct()
	compareStruct()
	initStruct()
	pointStruct()
	swapTest()
}

输出:

man: {andy 109 18}
 man2:  { 102 19}
man2.name = ""
man3 :  {mike 109 99}
man3 :  {mike 109 1073}
p1 == p2 ? true
p1 == p3 ? false
main temp size: 32
00temp { 0 0}
002 passValueStruct temp size: 32
01test: man {name1 0 33}
003  temp size: 32
02temp { 0 0}
&tmp = 0xc000004500
&temp.name = 0xc000004500
 main temp size: 1
p1 &{n1 102 19}
p2 &{n2 102 20}
p3 &{n3 102 21}
p4 &{n4 102 22}
p3 = 0xc000004620
&p3.name = 0xc000004620
p3, type= *main.Person
p3: &{n3 102 22}
main: 8
test2: 8
p3: &{Luffy 109 779}

说明:

type Person struct{
    name string
    sex string
    age int
}

普通变量定义和初始化:
    1.顺序初始化:依次将结构体内部所有成员初始化。
        var man Person = Person{"andy", 'm',20}
    2.指定成员初始化:
        man := Person{name:"rose", age:18} ----未初始化的成员变量,取该数据类型对应的默认值
普通变量的赋值和使用:
    使用“.”索引成员变量。
        var man3 Person
        man3.name = "mike"
        man3.sex = 'm'
        man3.age = 99

结构体变量的比较和赋值:
    1. 比较:只能使用==和!=不能> < >= <=
    2. 相同结构体类型(成员变量的类型、个数、顺序—致)变量之间可以直接赋值。

结构体地址:
    结构体变量的地址==结构体首个元素的地址。

结构体传参:
    unSafe.Sizeof(变量名) ——>此种类型的变量所占用的内存空间大小

    将结构体变量的值拷贝一份,传递。  ——几乎不用。内存消耗大,效率低。


指针变量定义和初始化:
    1. 顺序初始化:依次将结构体内部所有成员初始化。
        var man *Person = &Person{"andy", 'm', 20}
    2. new(Person)

指针索引成员变变量:
    使用“.”索引成员变量。
        var man3 Person
        man3.name = "mike"man3.sex = 'm'
        man3.age = 99
结构体地址:
    结构体指针变量的地址==结构体首个元素的地址.

结构体指针传参:
    unSafe.Sizeof(指针)︰不管何种类型的指针,在64位操作系统下,大小一致。均为8字节!!!
    将结构体变量地址值,传递(传引用)。  —— 使用频率非常高! ! !

练习:
    定义一个结构体,包含成员string、int、bool、[]string.
    在main函数中定义结构体“普通变量”,不初始化。封装函数initFunc,在该函数内初始化,main函数中打印查看。

结构体指针做函数返回值:
    不能返回局部变量的地址值。---- 局部变量保存栈帧上,函数调用结束后,栈帧释放。局部变量的地址不再受系统保护,随时可能分配给其他程序.    
    可以返回局部变量的值。
package main
import "fmt"

type Person3 struct {
	name string
	age int
	flg bool
	intereset []string
}
func initFunc(p *Person3){
	p.name = "Nami"
	p.age = 18
	p.flg = true
	p.intereset = append(p.intereset, "shopping")
	p.intereset = append(p.intereset, "sleeping")
}

//通过函数返回值,初始化结构体。
func initFunc2() *Person3{
	p := new(Person3)
	p.name = "Nami"
	p.age = 18
	p.flg = true
	p.intereset = append(p.intereset, "shopping")
	p.intereset = append(p.intereset, "sleeping")
	return p
	//不能返回局部变量的地址值。---- 局部变量保存栈帧上,函数调用结束后,栈帧释放。局部变量的地址不再受系统保护,随时可能分配给其他程序。
	//return *p
}


func main() {
	var person Person3
	fmt.Println( "00 person:", person)
	initFunc(&person)
	fmt.Println( "01 person:", person)
	p4 := initFunc2()
	fmt.Println(p4)
}

输出:

00 person: { 0 false []}
01 person: {Nami 18 true [shopping sleeping]}
&{Nami 18 true [shopping sleeping]}

go 结构体实例出来的对象,是值类型,对应直接指向一个内存空间(这个内存空间也有一个自己的内存地址),赋值时,直接将默认类型值改为赋值; 不同于引用类型是>> 引用类型是你要先指向一个地址,然后那个地址又指向另一个内存空间

posted @ 2022-03-06 23:36  ty1539  阅读(151)  评论(0编辑  收藏  举报