结构体拷贝
先声明一个狗狗的结构体
type Dog struct {name stringage 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指向空间1d3 := new(Dog) // d3指向空间2d1.name = "豆豆"d1.age = 2*d3 = *d1 // 指针的值拷贝,用*d1取出来的是"豆豆"结构体,赋值给*d3,那么d3指向的空间2会拷贝空间1的内容,两个空间还是独立的d1.name = "小喵"fmt.Println(d1) // this dog's name: 小喵, it's age: 2fmt.Println(d3) // this dog's name: 豆豆, it's age: 2
}
package mainimport ("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 stringUser1 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 := uma, _ := 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 = 999um.User2.UserId = 888a, _ = 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对其进行引用(打印值)