结构体拷贝
先声明一个狗狗的结构体
type Dog struct {
name string
age int8
}
// 重写String接口
func (Dog *Dog) String() string {
return fmt.Sprintf("this dog's name: %s, it's age: %d",Dog.name,Dog.age)
}
1.普通声明及值拷贝
可以看到输出的时候并没有用到重写的String方法(毕竟不是指针)
func main() {
d1 := Dog{"豆豆", 2}
d2 := d1 //值拷贝
d1.name = "小喵"
fmt.Println(d1) // {小喵 2}
fmt.Println(d2) // {豆豆 2}
}
2.普通声明及指针浅拷贝
可以看到输出的时候d1和d3的值是一样的,但是d1没有用到String,d3有
func main() {
d1 := Dog{"豆豆", 2}
d3 := &d1 //值拷贝
d1.name = "小喵"
fmt.Println(d1) // {小喵 2}
fmt.Println(d3) // this dog's name: 小喵, it's age: 2
}
3.结构体的new()声明及指针的值拷贝
可以看到输出的时候d1和d3的值是不一样的
func main() {
d1 := new(Dog) // d1指向空间1
d3 := new(Dog) // d3指向空间2
d1.name = "豆豆"
d1.age = 2
*d3 = *d1 // 指针的值拷贝,用*d1取出来的是"豆豆"结构体,赋值给*d3,那么d3指向的空间2会拷贝空间1的内容,两个空间还是独立的
d1.name = "小喵"
fmt.Println(d1) // this dog's name: 小喵, it's age: 2
fmt.Println(d3) // this dog's name: 豆豆, it's age: 2
}
package main
import (
"encoding/json"
"fmt"
)
type User struct {
UserId int64 `json:"user_id"`
RoomId int64 `json:"room_id"`
LiveIdStr string `json:"live_id"`
}
type UserManager struct {
AppId string
User1 User `json:"user1"`
User2 *User `json:"user2"`
}
func main() {
tmpUser := User{
UserId: 123456,
RoomId: 333003,
LiveIdStr: "zzt1",
}
tmpUser2 := User{
UserId: 123456,
RoomId: 333003,
LiveIdStr: "zzt1",
}
um := UserManager{
AppId: "app1080",
User1: tmpUser,
User2: &tmpUser2,
}
umCopy := um
a, _ := json.Marshal(um)
b, _ := json.Marshal(umCopy)
fmt.Printf("um:%+v, umCopy:%+v \n\n", string(a), string(b))
um.AppId = "修改1080"
um.User1.UserId = 999
um.User2.UserId = 888
a, _ = json.Marshal(um)
b, _ = json.Marshal(umCopy)
fmt.Printf("um:%+v, umCopy:%+v \n\n", string(a), string(b))
}
输出:
um:{"AppId":"app1080","user1":{"user_id":123456,"room_id":333003,"live_id":"zzt1"},"user2":{"user_id":123456,"room_id":333003,"live_id":"zzt1"}},
umCopy:{"AppId":"app1080","user1":{"user_id":123456,"room_id":333003,"live_id":"zzt1"},"user2":{"user_id":123456,"room_id":333003,"live_id":"zzt1"}}
um:{"AppId":"修改1080","user1":{"user_id":999,"room_id":333003,"live_id":"zzt1"},"user2":{"user_id":888,"room_id":333003,"live_id":"zzt1"}},
umCopy:{"AppId":"app1080","user1":{"user_id":123456,"room_id":333003,"live_id":"zzt1"},ser2":{"user_id":888,"room_id":333003,"live_id":"zzt1"}}
引用
区分指针引用和值引用,使用struct的时候,明确指针引用和值引用的区别很重要。
1.值引用赋值 比如 a:=b,这样修改a.name=“ls”,不会影响到b.name,值引用是复制结构体,开辟一块新的内存空间, a只是b的一个副本,而不是指向b的引用。
2.指针引用赋值 比如 a:=&b ,这样修改a.name=“ls”,会影响到b.name,指针引用是指向结构体内存地址的引用,同一块内存空间
总结1。值引用不会互相影响两个变量值的独立,指针引用则会互相影响,因为他们都指向同一块内存地址
总结2:值引用只是复制的一个副本,不是指向内存地址的引用;指针引用,指针是指向内存地址的引用,因此使用它操作的不是结构体的副本而是本身。
指针引用的时候,比如 b:=&a,此时b是指针,因此必须使用*b对其进行引用(打印值)