概念
-
对象定义
封装数据和行为
-
注意事项
不同于Java,go语言中不支持继承
结构体定义
-
使用关键字struct定义结构体
type Employee struct { Id string Name string Age int }
结构体创建
T{…}方式
-
结果为值类型
func TestCreateEmployee(t *testing.T) { e1 := Employee{"1", "张三", 10} t.Logf("张三个人信息:%v,变量类型:%T",e1,e1) }
new方式
-
内容介绍
用new 分配内存,它返回了一个指针,指向新分配的类型T 的零值
-
结果为指针类型
func TestCreateEmployee(t *testing.T) { e2 := new(Employee) e2.Name="李四" // 可以通过实例的指针访问成员不需要使用-> t.Logf("李四个人信息:%s,变量类型:%T",e2.Name,e2) }
&方式
-
结果为指针类型
func TestCreateEmployee(t *testing.T) { e3 := &Employee{"3","王五",13} t.Logf("王五个人信息:%v,变量类型:%T",e3,e3) }
创建并初始化
-
指定成员变量创建
e4 := &Employee{Name: "赵六",Id: "4",Age: 8}
构造函数
-
内容介绍
在Go语言中没有构造函数的概念,对象的创建通常交由一个全局的创建函数来完成,以NewXXX 来命名,表示“构造函数”
func NewEmployee(id string,name string,age int) *Employee { return &Employee{id,name,age} }
实际开发中,对于比较复杂的对象构造,才需要再额外创建"构造函数",因为go中的对象构造本身就比较简单
行为定义
-
样例代码
// 定义一个新的Worker类型 type Worker struct{ Name string } // > 为值类型Worker绑定Code()方法 func (w Worker) Code(){ fmt.Printf("%s think Coding is fun. 地址为:%x\n",w.Name,unsafe.Pointer(&w.Name)) } // > 为引用类型Worker绑定Debug()方法 func (w *Worker) Debug(){ fmt.Printf("%s think Debug is panic. 地址为:%x\n",w.Name,unsafe.Pointer(&w.Name)) }
方法传递
-
内容介绍
方法定义在值类型上时,GO编译器会隐式为其生成一个定义在引用类型上的方法(但是仍然不能修改接收调用者);
方法定义在指针类型上时,却不会自动为值类型添加该方法(因为定义在指针类型上的方法往往会修改接收者)。
-
案例代码
// 定义Gopher接口,该接口有两个方法 type Gopher interface{ Code() Debug() } func TestGopher(t *testing.T) { var gop1 Gopher = Worker{"Jack"} // 错误:因为值类型的Worker没有实现Debug()方法 var gop2 Gopher = &Worker{"Go"} // 正确,值类型上的方法"传递"到了引用类型上,相当于引用类型也实现了Code()方法 }
内存拷贝
-
内容介绍
创建的方法绑定在指针上时,可以避免内存拷贝;绑定在实例上时对应方法被调用,实例成员会进行值复制。所以一般建议绑定在指针上。
-
案例代码
func TestWorker(t *testing.T) { var w *Worker = &Worker{"CharlesYan"} t.Logf("方法接收者 %s 地址:%x",w.Name,unsafe.Pointer(&w.Name)) // 地址:c00005ade0 w.Code() // 地址为:c00005ae30 w.Debug() // 地址为:c00005ade0 }