diff --git a/eBook/10.1.md b/eBook/10.1.md index d97ae5c..bc3e8dd 100644 --- a/eBook/10.1.md +++ b/eBook/10.1.md @@ -209,11 +209,103 @@ type Rect2 struct {Min, Max *Point } **递归结构体** -**练习9.2** +结构体类型可以通过自身来定义。在结构体变量是链表或二叉树的元素(通常叫节点)时,这种方法会特别有用,此时节点包含指向临近节点的链接(地址)。如下所示,链表中的`su`,树中的`ri`h和`le`分别是指向另一个节点变量的指针。 -通过使用 unsafe 包中的方法来测试你电脑上一个整型变量占用多少个字节。 +链表: + +![](images/10.1_fig10.3.jpg?raw=true) + +这块的data域用于存放有些数据(比如float64),su指针指向后继节点。 + +Go代码: + +```go +type Node struct { + data float64 + su *Node +} +``` + +链表中的第一个元素叫`head`,它指向第二个元素;最后一个元素叫`tail`,它没有后继元素,所以它的su为nil值。当然真实的链接会有很多数据节点,并且链表可以动态增长或收缩。 + +同样地可以定义一个双向链表,它有一个前趋节点pr和一个后继节点su: + +```go +type Node struct { + pr *Node + data float64 + su *su +} +``` + +二叉树: + +![](images/10.1_fig10.4.jpg?raw=true) + +二叉树中每个节点最多能链接至两个节点:左节点(le)和右节点(ri),这两个节点本身又可以有左右节点,依次类推。树的顶层节点叫根节点(`root`),底层没有子节点的节点叫叶子节点(`leaves`),叶子节点的le和ri指针为空值。在Go中可以如下定义树: + +```go +type Tree strcut { + le *Tree + data float64 + ri *Tree +} +``` + +**结构体转换** + +Go中的类型转换遵循严格的规则。当为结构体定义了一个alias类型时,此结构体类型和它的alias类型都有相同的底层类型,它们可以如[Listing 10.3]那样互相转换,同时需要注意其中非法赋值或转换引起的编译错误: + +```go +package main +import "fmt" + +type number struct { + f float32 +} + +type nr number // alias type + +func main() { + a := number{5.0} + b := nr{5.0} + // var i float32 = b // compile-error: cannot use b (type nr) as type + float32 in assignment + // var i = float32(b) // compile-error: cannot convert b (type nr) to + type float32 + // var c number = b // compile-error: cannot use b (type nr) as type number in assignment + // needs a conversion: + var c = number(b) + fmt.Println(a, b, c) +} +``` + +输出: + + {5} {5} {5} + +**练习** + +*练习 10.1* + +vcard.go:定义结构体Address和VCard,后者包含一个人的名字、地址编号、出生日期和图像,试着选择正确的数据类型。构建一个自己的vcard并打印它的内容。 + +提示: + +VCard必须包含住址,它应该以值类型还是以指针类型放在VCard中呢? + +第二种会好点,因为它占用内存少。包含一个名字和两个指向地址的指针的Address结构体可以使用%v打印: + + {Kersschot 0x126d2b80 0x126d2be0} + +*练习 10.2* 修改*persionext1.go*,使它的参数upPerson不是一个指针,解释下二者的区别。 + +*练习 10.3* point.go:使用坐标X、Y定义一个二维Point结构体。同样地,对一个三维点使用它的极坐标定义一个Polar结构体。实现一个Abs()方法来计算一个Point表示的向量的长度,实现一个Scale方法,它将点的坐标乘以一个尺度因子(提示:使用math包里的Sqrt函数)( function Scale that multiplies the coordinates of a point with a scale +factor) + +*练习 10.3* rectangle.go:定义一个Rectangle结构体,它的长和宽是int类型,并定义方法Area()和Primeter()并测试 ## 链接 - [目录](directory.md) - 上一节:[10 结构(struct)与方法(method)](10.0.md) -- 下一节:[regexp 包](09.2.md) +- 下一节:[10.2 使用工厂方法创建结构体](10.2.md) diff --git a/eBook/images/10.1_fig10.3.jpg b/eBook/images/10.1_fig10.3.jpg new file mode 100644 index 0000000..2c59db7 Binary files /dev/null and b/eBook/images/10.1_fig10.3.jpg differ diff --git a/eBook/images/10.1_fig10.4.jpg b/eBook/images/10.1_fig10.4.jpg new file mode 100644 index 0000000..f040dbe Binary files /dev/null and b/eBook/images/10.1_fig10.4.jpg differ