GO42
1. 自定义类型和类型别名
自定义类型
type IZ int
这里IZ就是完全是一种新类型,然后我们可以使用下面的方式声明变量:
var a IZ = 5
- 类型转换时必须显式转换
- 不会拥有原基础类型所附带的方法
package main
import (
"fmt"
)
type A struct {
Face int
}
type Aa A // 自定义新类型Aa,没有基础类型A的方法
func (a A) f() {
fmt.Println("hi ", a.Face)
}
func main() {
var s A = A{ Face: 9 }
s.f()
var sa Aa = Aa{ Face: 9 }
sa.f()
}
编译错误信息:sa.f undefined (type Aa has no field or method f)
类型别名
type IZ = int
这种写法其实是定义了int类型的别名,类型别名在1.9中实现,可将别名类型和原类型这两个类型视为完全一致使用。
- 类型之间无需转换
- 拥有原基础类型所附带的方法
2. 结构体是值类型,可以使用 new 函数给一个新的结构体变量分配内存,它返回指向已分配内存的指针。表达式 new(Type) 和 &Type{} 是等价的。&struct1{a, b, c} 是一种简写,底层仍然会调用 new ()。
3. 嵌入与聚合
结构体中包含匿名(内嵌)字段叫嵌入或者内嵌;而如果结构体中字段包含了类型名,还有字段名,则是聚合。
type Human struct {
name string
}
type Person1 struct { // 内嵌
Human
}
type Person2 struct { // 内嵌, 这种内嵌与上面内嵌有差异
*Human
}
type Person3 struct{ // 聚合
human Human
}
嵌入在结构体中广泛使用,在Go语言中如果只考虑结构体和接口的嵌入组合方式,一共有下面四种:
- 1.在接口中嵌入接口:
这里指的是在接口中定义中嵌入接口类型,而不是接口的一个实例,相当于合并了两个接口类型定义的全部函数。下面只有同时实现了Writer和 Reader 的接口,才可以说是实现了Teacher接口,即可以作为Teacher的实例。Teacher接口嵌入了Writer和 Reader 两个接口,在Teacher接口中,Writer和 Reader是两个匿名(内嵌)字段。
type Writer interface{
Write()
}
type Reader interface{
Read()
}
type Teacher interface{
Reader
Writer
}
- 2.在接口中嵌入结构体:
这种方式在Go语言中是不合法的,不能通过编译。
type Human struct {
name string
}
type Writer interface {
Write()
}
type Reader interface {
Read()
}
type Teacher interface {
Reader
Writer
Human
}
存在语法错误,并不具有实际的含义,编译报错:
interface contains embedded non-interface Base
Interface 不能嵌入非interface的类型。
- 3.在结构体中内嵌接口:
初始化的时候,内嵌接口要用一个实现此接口的结构体赋值;或者定义一个新结构体,可以把新结构体作为receiver,实现接口的方法就实现了接口(先记住这句话,后面在讲述方法时会解释),这个新结构体可作为初始化时实现了内嵌接口的结构体来赋值。
package main
import (
"fmt"
)
type Writer interface {
Write()
}
type Author struct {
name string
Writer
}
// 定义新结构体,重点是实现接口方法Write()
type Other struct {
i int
}
func (a Author) Write() {
fmt.Println(a.name, " Write.")
}
// 新结构体Other实现接口方法Write(),也就可以初始化时赋值给Writer 接口
func (o Other) Write() {
fmt.Println(" Other Write.")
}
func main() {
// 方法一:Other{99}作为Writer 接口赋值
Ao := Author{"Other", Other{99}}
Ao.Write()
// 方法二:简易做法,对接口使用零值,可以完成初始化
Au := Author{name: "Hawking"}
Au.Write()
}
程序输出:
Other Write.
Hawking Write.
- 4.在结构体中嵌入结构体:
在结构体嵌入结构体很好理解,但不能嵌入自身值类型,可以嵌入自身的指针类型即递归嵌套。
在初始化时,内嵌结构体也进行赋值;外层结构自动获得内嵌结构体所有定义的字段和实现的方法。
4. channel
Go中通道可以是发送(send)、接收(receive)、同时发送(send)和接收(receive)。
// 定义接收的通道
receive_only := make (<-chan int)
// 定义发送的通道
send_only := make (chan<- int)
// 可同时发送接收
send_receive := make (chan int)
- chan<- 表示数据进入通道,要把数据写进通道,对于调用者就是发送。
- <-chan 表示数据从通道出来,对于调用者就是得到通道的数据,当然就是接收。
定义只发送或只接收的通道意义不大,一般用于在参数传递中
可以通过内置的close函数来关闭通道实现。
-
通道不需要经常去关闭,只有当没有任何可发送数据时才去关闭通道;
-
关闭通道后,无法向通道再发送数据(引发panic 错误后导致接收立即返回零值);
-
关闭通道后,可以继续向通道接收数据,不能继续发送数据;
-
对于nil 通道,无论收发都会被阻塞。