Go 语言学习-“面向对象”
struct 基本使用
可以使用 type 关键字定义一个别名
type myint int
func main() {
var val myint = 100
fmt.Printf("%T %d", val, val) // main.myint 100
}
定义一个结构体
type Book struct {
title string
auth string
}
func main() {
var book Book
book.title = "平凡的世界"
book.auth = "路遥"
fmt.Printf("%v", book) // %v 可以打印任意一种类型的格式化
// {平凡的世界 路遥}
}
但是注意,直接拿 Book 当函数形参是值传递的
// 这样修改 book 是不会影响原始值的
func changeBook(book Book) {
book.title = "liyuu_"
}
所以要传递指针进去
func changeBook(book *Book) {
book.title = "liyuu_"
}
func main() {
var book Book
book.title = "平凡的世界"
book.auth = "路遥"
changeBook(&book)
fmt.Printf("%v", book) // {liyuu_ 路遥}
}
Go 中的 “方法”
Go 中的类就是结构体绑定方法,但是不是在结构体内部绑定,而是外部绑定
方法能给用户自定义的类型添加新的行为。它和函数的区别在于方法有一个接收者,给一个函数添加一个接收者,那么它就变成了方法。接收者可以是值接收者,也可以是指针接收者。
Go 没有面向对象,而我们知道常见的 Java、C++ 等语言中,实现类的方法做法都是编译器隐式的给函数加一个 this 指针,而在 Go 里,这个 this 指针需要明确的申明出来,其实和其它 OO 语言并没有很大的区别。
Java 中的:
public class Circle {
private float radius;
private float getArea() {
return 3.14 * radius * radius;
}
}
而到了 Go
type Circle struct {
radius float64
}
func (c Circle) getArea() float64 {
//c.radius 即为 Circle 类型对象中的属性
return 3.14 * c.radius * c.radius
}
下面举个例子:
type Book struct {
title string
auth string
}
func (this Book) Show() {
fmt.Printf("%v ", this)
}
func (this Book) SetTitle(nv string) {
this.title = nv
}
func (this Book) GetAuth() string {
return this.auth
}
func main() {
//var book Book;
//book.auth = "吴承恩"
//book.title = "西游记"
book := Book{auth: "吴承恩", title: "西游记"} // 简写
book.Show()
book.SetTitle("人生")
book.Show()
}
但是注意:打印结果是
{西游记 吴承恩} {西游记 吴承恩}
因为上面那个 this 只是一个原结构体的拷贝,所以需要改成指针才能更改原始值(这里不用加 & 就能调用是因为,Go 默认加上 & 了)
func (this *Book) SetTitle(nv string) {
this.title = nv
}
// ...
book.SetTitle("人生")
// 打印结果
// {西游记 吴承恩} {人生 吴承恩}
值接受者和指针接收者
对于值接收者,如果调用者也是值对象,那么会将调用者的值拷贝一份,并执行方法,方法的调用不会影响到调用者值。 如果调用者是指针对象,那么会解引用指针对象为值,然后将解引的对象拷贝一份,然后执行方法。
对于指针接收者,如果调用者是值对象,会使用值的引用来调用方法,上例中,book.SetTitle("人生") 实际上是语法糖,实际执行的是 (&book).SetTitle(&book, "人生")