> For the complete documentation index, see [llms.txt](https://www.1024cx.top/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.1024cx.top/golang/ji-chu/struct.md).

# struct

## struct 嵌入 struct

可以起到类似于继承的作用，但不是真正的继承，[参考](/golang/ji-chu/feature.md)。

### struct内嵌匿名属性使用值类型和指针类型的区别?

内嵌值类型，给内嵌变量赋值时底层是创建了一个新的对象，发生的是值拷贝。

指针类型，发生的也是值拷贝，但拷贝的是指针，因此底层对象是同一个。

```go
type user struct {
	name  string
	email string
}

func (u *user) notify() {
	fmt.Printf("Send email to %s@<%s>\n", u.name, u.email)
}

func (u *user) setName(n string) {
	u.name = n
}

type admin struct {
	user         //设置内部类型
	level string //外部类新增的属性
}

// 覆盖内部类的方法
func (a *admin) notify() {
	fmt.Printf("Send admin email to %s@<%s>\n", a.name, a.email)
}

type operator struct {
	*user //指针形式内部类
	level string
}

func TestName(t *testing.T) {
	u1 := user{"zhangsan", "zhangsan@qq.com"}
	u2 := user{"lisi", "lisi@qq.com"}
	a := admin{
		user:  u1,
		level: "high",
	}
	o := operator{
		user:  &u2, // 指针变量
		level: "middle",
	}
	a.user.notify() //既可以通过内部类型调用方法。内部类的属性和方法始终可以通过内部类名进行访问
	a.notify()      //也可以直接通过外部类的对象访问，此时内部类型user的notify()就被覆盖了，触发的是admin.notify()
	a.setName("zhangsan1")
	o.setName("lisi1")
	fmt.Println(a.name, a.user.name, o.name, o.user.name) 
	fmt.Println(u1.name, u2.name)  // u1.name 没有被修改，因为u1传给admin的操作是发生了值拷贝，而u2传递的是指针，所以拷贝的也是指针，修改是同一个底层对象
}
```

## struct 嵌入 interface(struct+interface实现虚基类)

```go
type Model interface {
    Persist(context context.Context, msg interface{}) bool
}
type ModelImpl struct{}
func (m ModelImpl) Persist(context context.Context, msgIface interface{}) bool {
// 具体实现省略
}
type Service struct {
	model Model  // 内嵌interface，传入Service的Model类型ModelImpl就必须要实现Model接口
}

var serviceImpl = Service{
    Model:  ModelImpl,
}  // 这样，初始化的Service实例serviceImpl就可以给外部调用了，可以直接调用Model接口的方法
```

这样做的好处：

1. Service可以有多个不同的ModelImpl实体，多态，灵活。
2. 限制了ModelImpl必须要实现Model接口指定的方法。
