%T :使用Go语法输出的值的类型
%v:使用默认格式输出的内置或者自定义类型的值,或者是使用其类型的String()方式输出的自定义值,如果该方法存在的话
%p:以十六进制(基数为16)表示的一个值的地址,前缀为0x,字母使用小写的a-f表示

图片来自:https://www.cnblogs.com/guichenglin/p/12736203.html

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))
}

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)
	}
}