### 匿名字段
一般情况下,定义结构体的时候是字段名与其他类型一一对应,实际上go支持只提供类型,而不写字段名的
方式,也就是匿名字段,也称为嵌入字段 .当匿名字段也是一个结构体的时候,那么这个结构体所拥有的全
部字段都被隐式的引入了当前定义的这个结构体 .
#### 赋值
**注意 : 赋值的时候要么只写值,如果有一个字段写了字段名,那么所有的字段都要写字段名**.
~~~
type Person struct {
name string
gender byte
age int
}
type Student struct {
Person //只有类型,没有名字,继承了Person的成员
id int
addr string
}
func main() {
var s1 Student
s1.Person.name = "jack"
s1.Person.gender = '1'
s1.Person.age = 20
s1.id = 1
s1.addr = "杭州"
fmt.Println(s1)
//自动推导类型
s2 := Student{Person{"米兰", '0', 22}, 2, "北京"}
fmt.Printf("%+v\n", s2) //%+v 显示更详细
//指定成员初始化,没有初始化的为零值
s3 := Student{id: 4, addr: "上海"}
fmt.Printf("%+v\n", s3)
s4 := Student{Person: Person{name: "mike"}, id: 3}
fmt.Printf("%+v", s4)
}
~~~
~~~
{{jack 49 20} 1 杭州}
{Person:{name:米兰 gender:48 age:22} id:2 addr:北京}
{Person:{name: gender:0 age:0} id:4 addr:上海}
{Person:{name:mike gender:0 age:0} id:3 addr:}
~~~
#### 成员操作
~~~
s1 := Student{Person{"jack", 1, 20}, 1, "杭州"}
fmt.Printf("%+v\n", s1)
s1.id = 2
s1.Person.name = "mike"
fmt.Printf("%+v\n", s1)
s1.Person = Person{"milan",0,18}
fmt.Printf("%+v\n", s1)
~~~
#### 同名字段
就近原则,如果能在本作用域找到此成员,就操作此成员,如果找不到,就找继承的字段.
~~~
s1 := Student{Person{"jack",1,18},1,"milan","杭州"}
fmt.Printf("%+v\n",s1)
~~~
~~~
{Person:{name:jack gender:1 age:18} id:1 name:milan addr:杭州}
~~~
改为如下:
~~~
type Person struct {
name string
gender byte
age int
}
type Student struct {
Person
id int
//name string //这里注释掉了
addr string
}
func main() {
var s1 Student
s1.name = "jack"
fmt.Printf("%+v", s1)
}
~~~
~~~
{Person:{name:jack gender:0 age:0} id:0 addr:} //直接赋值到了继承的类型中的name上去了
~~~
#### 非结构体匿名字段
~~~
type myString string
type Person struct {
name string
gender byte
age int
}
type Student struct {
Person
int
myString
}
func main() {
s := Student{Person{"jack", 0, 18}, 666, "hello world"}
fmt.Printf("%+v\n", s)
fmt.Println(s.name, s.age, s.Person, s.int, s.myString)
}
~~~
~~~
{Person:{name:jack gender:0 age:18} int:666 myString:hello world}
jack 18 {jack 0 18} 666 hello world
~~~
### 结构体指针类型匿名字段
~~~
type myString string
type Person struct {
name string
gender byte
age int
}
type Student struct {
*Person
int
myString
}
func change(s Student) {
s.Person.name = "米兰"
s.int = 1000
}
func main() {
s := Student{&Person{"jack", 0, 18}, 666, "hello world"}
fmt.Printf("%+v\n", s)
fmt.Println(s.name, s.age, s.Person, s.int, s.myString)
change(s)
fmt.Println(s.Person, s.int)
//两种方式
var s2 Student
s2.Person = new(Person) //分配空间
s2.Person.name = "milan"
fmt.Println(s2)
}
~~~
~~~
{Person:0xc42000a060 int:666 myString:hello world}
jack 18 &{jack 0 18} 666 hello world
&{米兰 0 18} 666
{0xc42000a0e0 0 }
~~~
- 基本语法
- 申明变量
- 常量
- 数据类型
- 强制类型转换
- 获取命令行参数
- 指针
- 概述
- new函数
- 函数
- 概述
- 不定参数类型
- 有返回值
- 函数类型
- 回调函数
- 匿名函数和闭包
- 延迟调用defer
- 工程管理
- 工作区
- src,pkg和bin目录
- 复合类型
- 概述
- 数组
- 概述
- 声明并初始化
- 拷贝传值
- slice
- 概述
- 创建切片
- 切片截取
- 切片和底层数组的关系
- slice常用方法
- 切片做函数参数
- map
- 概述
- map操作
- 结构体
- 概述
- 结构体初始化
- 结构体比较
- 结构体作为函数参数
- 结构体前加&
- 面向对象
- 概述
- 匿名组合
- 方法
- 值语义和引用语义
- 方法集
- 方法的继承
- 方法重写
- 方法值
- 接口
- 接口定义和实现
- 多态的表现
- 接口继承
- 接口转换
- 空接口
- 类型断言
- 异常处理
- error接口
- panic
- recover
- 文本文件处理
- 字符串操作
- 正则表达式
- json处理
- 文件操作
- 标准设备文件操作
- 并发编程
- 概述
- 并发和并行
- go语言并发优势
- goroutine
- goroutine概述
- 创建goroutine
- 主协程先退出
- runtime包
- Gosched
- Goexit
- GOMAXPROCE
- channel
- 多资源竞争
- channel类型
- 无缓冲channel
- 有缓冲channel
- 关闭channel
- 单向channel
- 单向channel特性
- 定时器
- Timer
- Ticker
- select
- select作用
- 超时
- sync
- 竞争状态
- 网络编程
- 网络概述
- 网络协议
- 分层模型
- 网络分层架构
- 层与协议
- 每层协议的功能
- 链路层
- 网络层
- 传输层
- 应用层
- socket编程
- 组合和继承
- 注意事项
- 细节
- go语言实现队列
- google工程师golang
- 基础语法
- 内建容器
- 面向"对象"
- 依赖管理
- 面向接口
- 函数式编程
- 错误处理和资源管理
- 测试与性能调优
- goroutine
- channel
- golang问题集
- 断言和类型转换
- Go语言圣经
- 入门
- 程序结构
- 命名
- 声明
- 变量
- 赋值
- 类型
- 包和文件
- 作用域
- 基础数据类型
- 整数
- 浮点数
- 复数
- 布尔型
- 字符串
- 常量
- 复合数据类型
- 数组
- slice
- map
- 结构体
- json
- 文本和HTML模板
- 函数
- 函数声明
- 错误
- 函数值
- 匿名函数
- defer
- panic
- recover
- 方法
- 方法声明
- 指针对象的方法
- 封装
- 接口
- 说明
- 接口是合约
- 实现接口的条件
- 接口值
- 类型断言
- 通过类型断言询问行为
- 类型开关
- Goroutines和Channels
- 协程
- channels
- 无缓冲channel
- 串联的channel
- 有缓冲channel
- 并发的循环
- select多路复用
- 并发的退出
- 并发问题的自我思考
- 基于共享变量的并发
- 竞争条件
- 互斥锁
- 读写锁
- 内存同步
- sync.Once
- 协程和线程
- 包和工具
- 测试
- 反射
- 什么是反射
- 为什么需要反射
- reflect.Type和reflect.Value
- 通过reflect.Value修改值
- 底层编程
