# 10.1 结构体定义

``````type identifier struct {
field1 type1
field2 type2
...
}``````

`type T struct {a, b int}` 也是合法的语法，它更适用于简单的结构体。

``````var s T
s.a = 5
s.b = 8``````

``````var t *T
t = new(T)``````

``````package main
import "fmt"

type struct1 struct {
i1  int
f1  float32
str string
}

func main() {
ms := new(struct1)
ms.i1 = 10
ms.f1 = 15.5
ms.str= "Chris"

fmt.Printf("The int is: %dn", ms.i1)
fmt.Printf("The float is: %fn", ms.f1)
fmt.Printf("The string is: %sn", ms.str)
fmt.Println(ms)
}``````

``````The int is: 10
The float is: 15.500000
The string is: Chris
&{10 15.5 Chris}``````

``````type myStruct struct { i int }
var v myStruct    // v是结构体类型变量
var p *myStruct   // p是指向一个结构体类型变量的指针
v.i
p.i``````

``````    ms := &struct1{10, 15.5, "Chris"}
// 此时ms的类型是 *struct1``````

``````    var ms struct1
ms = struct1{10, 15.5, "Chris"}``````

``````type Interval struct {
start int
end   int
}``````

``````intr := Interval{0, 3}            (A)
intr := Interval{end:5, start:1}  (B)
intr := Interval{end:5}           (C)``````

``type Point struct { x, y int }``

``````package main
import (
"fmt"
"strings"
)

type Person struct {
firstName   string
lastName    string
}

func upPerson(p *Person) {
p.firstName = strings.ToUpper(p.firstName)
p.lastName = strings.ToUpper(p.lastName)
}

func main() {
// 1-struct as a value type:
var pers1 Person
pers1.firstName = "Chris"
pers1.lastName = "Woodward"
upPerson(&pers1)
fmt.Printf("The name of the person is %s %sn", pers1.firstName, pers1.lastName)

// 2—struct as a pointer:
pers2 := new(Person)
pers2.firstName = "Chris"
pers2.lastName = "Woodward"
(*pers2).lastName = "Woodward"  // 这是合法的
upPerson(pers2)
fmt.Printf("The name of the person is %s %sn", pers2.firstName, pers2.lastName)

// 3—struct as a literal:
pers3 := &Person{"Chris","Woodward"}
upPerson(pers3)
fmt.Printf("The name of the person is %s %sn", pers3.firstName, pers3.lastName)
}``````

``````The name of the person is CHRIS WOODWARD
The name of the person is CHRIS WOODWARD
The name of the person is CHRIS WOODWARD``````

Go 语言中，结构体和它所包含的数据在内存中是以连续块的形式存在的，即使结构体中嵌套有其他的结构体，这在性能上带来了很大的优势。不像 Java 中的引用类型，一个对象和它里面包含的对象可能会在不同的内存空间中，这点和 Go 语言中的指针很像。下面的例子清晰地说明了这些情况：

``````type Rect1 struct {Min, Max Point }
type Rect2 struct {Min, Max *Point }``````

Go 代码：

``````type Node struct {
data    float64
su      *Node
}``````

``````type Node struct {
pr      *Node
data    float64
su      *Node
}``````

``````type Tree strcut {
le      *Tree
data    float64
ri      *Tree
}``````

Go 中的类型转换遵循严格的规则。当为结构体定义了一个 alias 类型时，此结构体类型和它的 alias 类型都有相同的底层类型，它们可以如示例 10.3 那样互相转换，同时需要注意其中非法赋值或转换引起的编译错误。

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

``````提示：
VCard 必须包含住址，它应该以值类型还是以指针类型放在 VCard 中呢？

factor）。