定义结构体只是对内存布局的一种描述,只有当结构体实例化时,才会真正地分配内存。因此,必须在定义结构体并实例化以后,才能使用成员变量字段。
实例化的物理意义就是根据结构体定义的格式,创建一段独立的内存地址范围。结构体的实例与实例之间,内存地址范围是完全独立不同的。go有多种结构体实例化的方式。
1. 基本的结构体实例化
- 格式
var 结构体实例 结构体类型
- 使用
.
来访问结构体实例的成员变量
对平台点坐标结构体Point,进行实例化
type Point struct{
X int //
Y int
}
var p Point
p.X = 10
p.Y = 20
Point为自定义的平面点坐标结构体,p为结构体实例,使用.
来访问结构体成员变量,如p.X
和p.Y
等。结构体成员变量的赋值方法,与普通变量一致。
2. 创建指针类型的结构体实例化(常用)
在go语言中,我们可以使用关键字new对数据类型(基本类型:整型、浮点型、字符串,复合类型:结构体)实例化,结构体在new实例化后形成指针类型的结构体实例。
- 格式
变量ins := new(数据类型T)
数据类型T可以为整型、字符串等基本类型,也可以是结构体。这里以结构体为例,结构体T被实例化后,得到结构体指针*T,保存在变量ins中。
- 使用new实例化结构体
在go中,我们可以像访问普通结构体一样,使用.
访问结构体指针的成员变量。定义游戏玩家结构体Player,拥有成员变量:名字Name、生命值HealthPoint和魔法值MagicPoint
type Player struct{
Name string
HealthPoint int
MagicPoint int
}
// 实例化玩家结构体Player
tank := new(Player)
// 结构体实例化后,对成员变量赋值
tank.Name = "Canon"
tank.HealthPoint = 300
在成员赋值上,new结构体实例化与基本结构体实例化的写法一致,都是使用.
。
注:在C/C++语言中,使用new实例化类型(基本类型、结构体)后,访问其实例的成员变量必须使用
->
,而go语言使用了语法糖技术,把ins.Name转换成(*ins).Name
3. 取结构体内存地址的实例化(最常用)
在go语言中,使用&取内存地址,视为对结构体类型进行一次new实例化。
- 格式
变量ins := &结构体T{}
使用&得到结构体实例内存地址,实例是结构体指针类型*T。{}内是结构体实例初始化内容,可以是实际值,也可以是变量。详见构造函数——模拟构造函数重载
。
- 使用&实例化结构体
// 定义结构体Command,表示命令行指令
type Command struct {
Name string // 指令名称
Var *int // 指令绑定变量,Var绑定了一个*int整型指针
Comment string // 指令的注释
}
var version int = 1.0 // 定义命令绑定的整型变量:版本号。版本值version可以与指令绑定变量Var随时保持同步。
// 使用&,对结构体取内存地址的实例化
cmd := &Command{}
// 初始化结构体实例cmd的成员变量
cmd.Name = "version"
cmd.Var = &version // 取变量version的内存地址,得到指针类型*int,符合Var的*int类型要求
cmd.Comment = "show version"
使用函数封装上述初始化结构体实例的过程
type Command struct {
Name string // 指令名称
Var *int // 指令绑定变量,Var绑定了一个*int整型指针
Comment string // 指令的注释
}
func newCommand(name string, varref *int, comment string) *Command {
return &Command{ // 返回结构体指针
Name: name, // 为结构体实例传递函数入参
Var: varref,
Comment: comment,
}
}
var version int = 1.0
cmd = newCommand(
"version",
&version,
"show version",
)