package main
import(
"fmt"
// "github.com/mattn/go-runewidth"
// "net/http"
// "text/template"
)
// struct 是一个值类型 深拷贝 和浅拷贝 常量声明是要初始化
type Human struct{
name string
age int
sex byte
}
type dog struct{
name string
age int
color string
kind string
}
type teacher struct {
name string
age int
sex int
}
type emp struct {
name string
age int
sex int
}
func main(){
//new方法声明初始化一个变量
emp1 := new(emp)
emp1.name = "david2"
emp1.sex = 333
emp1.age = 222
emp2 := emp1
fmt.Printf("%T,%v,%p \n",emp1,emp1,emp1)//*main.emp,&{david2 222 333},0xc000048400
fmt.Printf("%T,%v,%p \n",emp2,emp2,emp2)//*main.emp,&{david2 222 333},0xc000048400
emp2.name = "maike"
emp2.sex = 4444
fmt.Printf("%T,%v,%p \n",emp1,emp1,emp1)//*main.emp,&{maike 222 4444},0xc000048400
fmt.Printf("%T,%v,%p \n",emp2,emp2,emp2)//*main.emp,&{maike 222 4444},0xc000048400
fmt.Println("----------------------")
//深拷贝 会赋值全部的内容 内容一样但是地址不一样 修改任何一个后地址不一样 内容也会一样
h1:= Human{name:"聂伟博",age:28,sex:0}
h2:= h1
fmt.Printf("h1:%T,%v,%p \n",h1,h1,&h1) //h1:main.Human,{聂伟博 28 0},0xc0000484c0
fmt.Printf("h2:%T,%v,%p \n",h2,h2,&h2) //h2:main.Human,{聂伟博 28 0},0xc0000484e0
fmt.Println("-----------------------")
h2.name = "dvid"
fmt.Printf("h2修改后:%T,%v,%p \n",h2,h2,&h2) //h2修改后:main.Human,{dvid 28 0},0xc0000484e0
fmt.Printf("h1:%T,%v,%p \n",h1,h1,&h1) //h1:main.Human,{聂伟博 28 0},0xc0000484c0
fmt.Println("------------------------")
changeName(h1)//对象传到函数里面也是深拷贝
fmt.Println("------------------------")
fmt.Printf("h1:%T,%v,%p \n",h1,h1,&h1)
fmt.Println("---------------------------")
//浅拷贝
fmt.Println("浅拷贝")
d1:=dog{name:"贝贝",age:12,color:"黄色",kind:"二哈"}
d3:=&d1
fmt.Printf("d1:%T,%v,%p \n",d1,d1,&d1) //d1:main.dog,{贝贝 12 黄色 二哈},0xc000034140
fmt.Printf("d3:%T,%v,%p \n",d3,d3,d3) //d3:*main.dog,&{贝贝 12 黄色 二哈},0xc000034140
d3.name = "皮皮"
d3.color = "白色"
d3.kind = "萨摩"
fmt.Printf("d1:%T,%v,%p \n",d1,d1,&d1) //d1:main.dog,{皮皮 12 白色 萨摩},0xc000034140
fmt.Printf("d3:%T,%v,%p \n",d3,d3,d3) //d3:*main.dog,&{皮皮 12 白色 萨摩},0xc000034140
fmt.Println("---------------------------")
//new操作浅拷贝
fmt.Println("new操作浅拷贝:")
d4 := new (dog)
d4.age = 11
d4.name = "球球"
d4.color = "棕色"
d4.kind = "金毛"
d5 := d4
fmt.Printf("d4:%T,%v,%p \n",d4,d4,d4) //d4:*main.dog,&{球球 11 棕色 金毛},0xc00004a340
fmt.Printf("d5:%T,%v,%p \n",d5,d5,d5) //d5:*main.dog,&{球球 11 棕色 金毛},0xc00004a340
d5.name = "本本"
d5.color = "黑色"
fmt.Printf("d4:%T,%v,%p \n",d4,d4,d4) //d4:*main.dog,&{本本 11 黑色 金毛},0xc00004a340
fmt.Printf("d5:%T,%v,%p \n",d5,d5,d5) //d5:*main.dog,&{本本 11 黑色 金毛},0xc00004a340
teache := teacher{
name:"nieweibo",
age:23,
sex:3,
}
fmt.Printf("teacher类型:%T",teache)
}
func changeName(h Human){
h.name = "danil"
// h.age = 13
fmt.Printf("函数体内的修改后h1:%T,%v,%p \n",h,h,h)
}
打印的结果:
*main.emp,&{david2 222 333},0xc000048400
*main.emp,&{david2 222 333},0xc000048400
*main.emp,&{maike 222 4444},0xc000048400
*main.emp,&{maike 222 4444},0xc000048400
----------------------
h1:main.Human,{聂伟博 28 0},0xc0000484c0
h2:main.Human,{聂伟博 28 0},0xc0000484e0
-----------------------
h2修改后:main.Human,{dvid 28 0},0xc0000484e0
h1:main.Human,{聂伟博 28 0},0xc0000484c0
------------------------
函数体内的修改后h1:main.Human,{danil 28 0},%!p(main.Human={danil 28 0})
------------------------
h1:main.Human,{聂伟博 28 0},0xc0000484c0
---------------------------
浅拷贝
d1:main.dog,{贝贝 12 黄色 二哈},0xc00004a100
d3:*main.dog,&{贝贝 12 黄色 二哈},0xc00004a100
d1:main.dog,{皮皮 12 白色 萨摩},0xc00004a100
d3:*main.dog,&{皮皮 12 白色 萨摩},0xc00004a100
---------------------------
new操作浅拷贝:
d4:*main.dog,&{球球 11 棕色 金毛},0xc00004a2c0
d5:*main.dog,&{球球 11 棕色 金毛},0xc00004a2c0
d4:*main.dog,&{本本 11 黑色 金毛},0xc00004a2c0
d5:*main.dog,&{本本 11 黑色 金毛},0xc00004a2c0
总结:凡是%v占位符对应的值前面有&这个符号的说明是指针类型,变量的前面就不用加& 如果没有就需要加&
不打印的话如何知道什么时候加&这个呢?首先如果你定义一个变量val无论这个变量是什么类型,那么这个变量一定要在前面加上&来匹配%p占位符,如果你深拷贝这个值val那么这两个变量都需要加上&,如果浅拷贝val那么浅拷贝只有的变量val2就是一个指针类型 不需要加上&符号。
new(dog)关键字之后 使用 b:=a 咋一看是深拷贝 其实是浅拷贝,b是拷贝了a的内存
下面是个浅显的例子:
b := a 这是深拷贝 会生成两个内存地址, b:=&a 这是浅拷贝a,b公用a的内存地址,b就是指针类型
a := 12
b := & a
fmt.Printf("a:%T,%v,%p \n",a,a,&a) //a:int,12,0xc00004e090
fmt.Printf("b:%T,%v,%p \n",b,b,b) //b:*int,0xc00004e090,0xc00004e090