[关闭]
@adamhand 2019-02-13T12:37:51.000000Z 字数 1844 阅读 775

golang--结构体取代类


Go 支持面向对象吗?

Go 并不是完全面向对象的编程语言。Go语言官网对此的解答为:

可以说是,也可以说不是。虽然 Go 有类型和方法,支持面向对象的编程风格,但却没有类型的层次结构。Go中没有类的概念,但是可以使用结构体来代替,Go 也可以将结构体嵌套使用,这与子类化(Subclassing)类似,但并不完全相同。此外,Go 提供的特性比 C++ 或 Java 更为通用:子类可以由任何类型的数据来定义,甚至是内建类型(如简单的“未装箱的”整型)。这在结构体(类)中没有受到限制。

使用结构体,而非类

Go 不支持类,而是提供了结构体。结构体中可以添加方法。这样可以将数据和操作数据的方法绑定在一起,实现与类相似的效果。下面通过一个例子来理解。

首先,建立employee.go文件夹,它的目录结构如下:

workspacepath -> oop -> employee -> employee.go

内容如下:

  1. package employee
  2. import (
  3. "fmt"
  4. )
  5. type Employee struct {
  6. FirstName string
  7. LastName string
  8. TotalLeaves int
  9. LeavesTaken int
  10. }
  11. func (e Employee) LeavesRemaining() {
  12. fmt.Printf("%s %s has %d leaves remaining", e.FirstName, e.LastName, (e.TotalLeaves - e.LeavesTaken))
  13. }

接着在 oop 文件夹里创建一个文件,命名为 main.go。

现在目录结构如下所示:

workspacepath -> oop -> employee -> employee.go
workspacepath -> oop -> main.go

  1. main.go 的内容如下所示:
  2. package main
  3. import "oop/employee"
  4. func main() {
  5. e := employee.Employee {
  6. FirstName: "Sam",
  7. LastName: "Adolf",
  8. TotalLeaves: 30,
  9. LeavesTaken: 20,
  10. }
  11. e.LeavesRemaining()
  12. }

执行main.go程序,会打印输出:

  1. Sam Adolf has 10 leaves remaining

注意:关于import引入自定义包的问题
import的包都是相对$GOPATH/src目录引入的,如果项目的import路径是这样写的:
import "github.com/yourname/projectname"
需要将项目代码放置在:
$GOAPTH/src/github.com/yourname/projectname/

如果项目的import是这样写的:
import "message"
则将message.go放到:
$GOAPTH/src/message/目录下即可。


使用 New() 函数,而非构造器

Java等语言使用构造函数来对对象进行初始化,而golang使用New()函数,该函数是由程序员提供的,就类似于Java中的set方法。

Java中的Set方法一般是对private变量进行初始化,相同的,使用New()函数进行初始化的结构体一般不可对外引用,即首字母小写。

  1. package employee
  2. import (
  3. "fmt"
  4. )
  5. type employee struct {
  6. firstName string
  7. lastName string
  8. totalLeaves int
  9. leavesTaken int
  10. }
  11. func New(firstName string, lastName string, totalLeave int, leavesTaken int) employee {
  12. e := employee {firstName, lastName, totalLeave, leavesTaken}
  13. return e
  14. }
  15. func (e employee) LeavesRemaining() {
  16. fmt.Printf("%s %s has %d leaves remaining", e.firstName, e.lastName, (e.totalLeaves - e.leavesTaken))
  17. }

main函数如下:

  1. package main
  2. import "oop/employee"
  3. func main() {
  4. e := employee.New("Sam", "Adolf", 30, 20)
  5. e.LeavesRemaining()
  6. }

程序的执行结果为:

  1. Sam Adolf has 10 leaves remaining
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注