Go 允许定义新的类型,可以通过关键字 type 实现:
type foo int
如上我们创建了一个新的类型 foo 作用跟 int 一样。创建更加复杂的类型需要用到 struct 关键字。这有个在一个数据结构中记录某人的姓名(string)和年龄(int),并且使其成为一个新的类型的例子:
package main
import "fmt"
type NameAge struct {
name string // 不导出
age int // 不导出
}
func main() {
a := new(NameAge)
a.name = "Pete" ; a.age = 42
fmt.Printf("%v\n", a)
}
通常,fmt.Printf(“%v\n”, a) 的输出是&{Pete 42}
Go 知道如何打印结构。如果仅想打印某一个,或者某几个结构中的字段,需
要使用 .
fmt.Printf("%s", a.name) // %s 格式化字符串
结构字段
之前已经提到结构中的项目被称为field。没有字段的结构:struct {}
或者有四个c 字段的:
struct {
x, y int
A *[]int
F func()
}
如果省略字段的名字,可以创建匿名字段,例如:
struct {
T1 // 字段名字是 T1
*T2 // 字段名字是 T2
P.T3 // 字段名字是 T3
x, y int // 字段名字是 x 和 y
}
注意首字母大写的字段可以被导出,也就是说,在其他包中可以进行读写。字段名以小写字母开头是当前包的私有的。
方法
可以对新定义的类型创建函数以便操作,可以通过两种途径:
- 创建一个函数接受这个类型的参数。
(你可能已经猜到了)这是 函数调用。func doSomething(n1 *NameAge, n2 int) { /* */ }
- 创建一个工作在这个类型上的函数(参阅在 2.1 中定义的接收方):
这是方法调用,可以类似这样使用:func (n1 *NameAge) doSomething(n2 int) { /* */ }
使用函数还是方法是由程序员决定的,但是如果想要满足接口就只能使用方法。如果没有这方面的需求,那就由个人品味决定了。var n *NameAge n.doSomething(2)
下面的类型定义中有一些微小但是很重要的不同之处。
我们假设有如下代码:
// Mutex 数据类型有两个方法,Lock 和 Unlock。
type Mutex struct { /* Mutex 字段 */ }
func (m *Mutex) Lock() { /* Lock 实现 */ }
func (m *Mutex) Unlock() { /* Unlock 实现 */ }
现在用两种不同的风格创建了两个数据类型:
type NewMutex Mutex
type PrintableMutex struct {Mutex }
现在 NewMutux 等同于 Mutex,但是它没有任何 Mutex 的方法。换句话说,它的方法
是空的。但是 PrintableMutex 已经从 Mutex 继承了方法集合。*PrintableMutex 的方法集合包含了 Lock 和 Unlock 方法,被绑定到其匿名字段 Mutex。