%T :使用Go语法输出的值的类型
%v:使用默认格式输出的内置或者自定义类型的值,或者是使用其类型的String()方式输出的自定义值,如果该方法存在的话
%p:以十六进制(基数为16)表示的一个值的地址,前缀为0x,字母使用小写的a-f表示
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5iMwkDM0QzYzQjY2MGMjZ2YyYzXwUzNwUTM0EzLcdDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
1、浅复制(1)new()和:=
package main
import "fmt"
type dog struct {
name string
age int
sex int
}
func main() {
dog1 := new(dog)
dog1.name = "dog1"
dog1.age = 11
dog1.sex = -1
dog2 := dog1
fmt.Printf("%T %v %p\n", dog1, dog1, dog1)
fmt.Printf("%T %v %p\n", dog2, dog2, dog2)
dog2.name = "dog2"
dog2.age = 12
dog2.sex = 2
fmt.Printf("%T %v %p\n", dog1, dog1, dog1)
fmt.Printf("%T %v %p\n", dog2, dog2, dog2)
}
2、浅复制(2)结构名{}和 :=&
package main
import "fmt"
type dog struct {
name string
age int
sex int
}
func main() {
dog1 := dog{
name: "dog1",
age: 11,
sex: -1,
}
dog2 := &dog1
fmt.Printf("%T %v %p\n", dog1, dog1, &dog1)
fmt.Printf("%T %v %p\n", dog2, dog2, dog2)
dog2.name = "dog2"
dog2.age = 12
dog2.sex = 2
fmt.Printf("%T %v %p\n", dog1, dog1, &dog1)
fmt.Printf("%T %v %p\n", dog2, dog2, dog2)
}
3、浅复制(3) 切片
package main
import (
"fmt"
"unsafe"
)
func main() {
slice_test := []int{1, 2, 3, 4, 5}
fmt.Println(unsafe.Sizeof(slice_test))
fmt.Printf("main:%#v,%#v,%#v\n\n", slice_test, len(slice_test), cap(slice_test))
slice_value(slice_test)
fmt.Printf("after slice_test,main:%#v,%#v,%#v\n\n", slice_test, len(slice_test), cap(slice_test))
slice_ptr(&slice_test)
fmt.Printf("after slice_ptr,main:%#v,%#v,%#v\n\n", slice_test, len(slice_test), cap(slice_test))
fmt.Println(unsafe.Sizeof(slice_test))
}
func slice_value(slice_test []int) {
slice_test[1] = 100 // 函数里的slice确实有被修改
slice_test = append(slice_test, 6) // 函数外的不变
fmt.Printf("slice_value:%#v,%#v,%#v\n\n", slice_test, len(slice_test), cap(slice_test))
}
func slice_ptr(slice_test *[]int) { // 这样才能修改函数外的slice
(*slice_test)[1] = 10
*slice_test = append(*slice_test, 7)
fmt.Printf("slice_ptr:%#v,%#v,%#v\n\n", *slice_test, len(*slice_test), cap(*slice_test))
}
unsafe.sizeof()
4、 深复制(1)结构名{}和:=
package main
import "fmt"
type dog struct {
name string
age int
sex int
}
func main() {
dog1 := dog{
name: "dog1",
age: 11,
sex: -1,
}
dog2 := dog1
fmt.Printf("%T %v %p\n", dog1, dog1, &dog1)
fmt.Printf("%T %v %p\n", dog2, dog2, &dog2)
dog2.name = "dog2"
dog2.age = 12
dog2.sex = 2
fmt.Printf("%T %v %p\n", dog1, dog1, &dog1)
fmt.Printf("%T %v %p\n", dog2, dog2, &dog2)
}
5、深复制(2)指针
package main
import "fmt"
type dog struct {
name string
age int
sex int
}
func main() {
dog1 := &dog{
name: "dog1",
age: 11,
sex: -1,
}
dog1Ptr := *dog1
dog2 := &dog1Ptr
fmt.Printf("%T %v %p\n", dog1, dog1, dog1)
fmt.Printf("%T %v %p\n", dog2, dog2, dog2)
dog2.name = "dog2"
dog2.age = 12
dog2.sex = 2
fmt.Printf("%T %v %p\n", dog1, dog1, dog1)
fmt.Printf("%T %v %p\n", dog2, dog2, dog2)
}
评论区说的没错,以上只能处理没有指针属性的结构体
golang 完全是按值传递,所以正常的赋值都是值拷贝,当然如果类型里面嵌套的有指针,也是指针值的拷贝,此时就会出现两个类型变量的内部有一部分是共享的。
package main
import "fmt"
type dog struct {
name string
age int
sex int
son *dog
}
func main() {
dogSon := dog{
name :"dogSon1",
age:1,
sex: 1,
son:nil,
}
dog1 := dog{
name: "dog1",
age: 11,
sex: -1,
son:&dogSon,
}
dog2 := dog1
fmt.Printf("Before Change dog2.son's information:\n")
fmt.Printf("do1.son:%T %v %p\n", dog1.son, dog1.son, &dog1.son)
fmt.Printf("dog2.son:%T %v %p\n", dog2.son, dog2.son, &dog2.son)
fmt.Printf("\nAfter Change dog2.son's information:\n")
dog2.son.name = "dogSon2"
dog2.son.age = 2
dog2.son.sex = 2
fmt.Printf("%T %v %p\n", dogSon, dogSon, &dogSon)
fmt.Printf("dog1.son:%T %v %p\n", dog1.son, dog1.son, &dog1.son)
fmt.Printf("dog2.son:%T %v %p\n", dog2.son, dog2.son, &dog2.son)
}
6、基于序列化和反序列化来实现对象的深度复制
package main
import (
"bytes"
"encoding/gob"
"fmt"
)
type Dog struct { // 结构体序列化时,需要序列化的字段需要首字母大写。
Name string
Age int
Sex int
Son *Dog
}
func deepcopy(dst, src interface{}) error{
var buffer bytes.Buffer //构造缓冲区
// 序列化,生成gob编码器并编码
if err:= gob.NewEncoder(&buffer).Encode(src);err!=nil{
return err
}
// 反序列化,构造gob解码器,解码
return gob.NewDecoder(bytes.NewBuffer(buffer.Bytes())).Decode(dst)
}
func main() {
dogSon := Dog{
Name :"dogSon1",
Age:1,
Sex: 1,
Son:nil,
}
dog1 := Dog{
Name: "dog1",
Age: 11,
Sex: -1,
Son:&dogSon,
}
var dog2 Dog
err := deepcopy(&dog2, &dog1)
if err != nil{
fmt.Println(err)
}else {
fmt.Printf("Before Change dog2.Son's information:\n")
fmt.Printf("do1.Son:%T %v %p\n", dog1.Son, dog1.Son, &dog1.Son)
fmt.Printf("dog2.Son:%T %v %p\n", dog2.Son, dog2.Son, &dog2.Son)
fmt.Printf("\nAfter Change dog2.Son's information:\n")
dog2.Son.Name = "dogSon2"
dog2.Son.Age = 2
dog2.Son.Sex = 2
fmt.Printf("%T %v %p\n", dogSon, dogSon, &dogSon)
fmt.Printf("dog1.Son:%T %v %p\n", dog1.Son, dog1.Son, &dog1.Son)
fmt.Printf("dog2.Son:%T %v %p\n", dog2.Son, dog2.Son, &dog2.Son)
}
}