写点什么

深入理解 Go 语言中的封装机制

作者:宇宙之一粟
  • 2023-04-23
    中国香港
  • 本文字数:1962 字

    阅读完需:约 6 分钟

深入理解 Go 语言中的封装机制

什么是封装

封装,也就是所谓的信息隐藏,是面向对象编程的一个重要方面。封装被定义为将数据包裹在一个单一的单元下。它是将代码和它所操作的数据绑定在一起的机制。从另一个角度来说,封装是一个保护罩,防止数据被这个保护罩外的代码访问。


在面向对象的语言中,一个类的变量或数据是隐藏的,不受任何其他类的影响,只能通过它们所声明的自己类的任何成员函数来访问。但是 Go 语言不支持类和对象。因此,在 Go 语言中,封装是通过使用包来实现的。Go 语言提供两种不同类型的标识符,即可导出 exported 的和不被导出 unexported 的标识符。封装是通过从包中导出的元素(变量、函数、方法、字段、结构)实现的,它有助于控制元素(变量、函数、方法、字段、结构)的可见性。如果定义这些元素的包在你的程序中可用,那么这些元素就是可见的。

Go 中的封装


Go 与经典的 OOP 语言不同。它没有类、对象和访问修改器的概念。相反,它有一个包的概念。


Golang 在包的层次上提供封装。Go 没有任何 publicprivateprotected 关键字。控制可见性的唯一机制是使用大写和非大写的格式:

  • 大写的标识符是可以导出的。大写字母表示这是一个导出的标识符。

  • 非大写的标识符不被导出。小写表示该标识符不被导出,只在同一包内被访问。


有五种可以导出或不能被导出的标识符:

  1. 结构体

  2. 结构体方法

  3. 结构体字段

  4. 函数

  5. 变量


让我们看一个显示上述所有标识符的导出和不导出的示例。请参阅下面的 data.go:


package model
import "fmt"
var ( SchoolName = "test" schoolLocation = "somecity")
//Person structtype Person struct { Name string age int}
//GetAge of personfunc (p *Person) GetAge() int { return p.age}
func (p *Person) getName() string { return p.Name}
type company struct {}
//GetPerson get the person objectfunc GetPerson() *Person { p := &Person{ Name: "test", age: 21, } fmt.Println("Model Package:") fmt.Println(p.Name) fmt.Println(p.age) return p}
func getSchoolName() string { return SchoolName}
复制代码


测试 test.go


package model
import "fmt"
//Test functionfunc Test() { p := &Person{ Name: "test", age: 21, } fmt.Println(p) c := &school{} fmt.Println(c) //STRUCTURE'S METHOD fmt.Println(p.GetAge()) fmt.Println(p.getName()) //STRUCTURE'S FIELDS fmt.Println(p.Name) fmt.Println(p.age) //FUNCTION person2 := GetPerson() fmt.Println(person2) companyName := getSchoolName() fmt.Println(schoolName) //VARIBLES fmt.Println(schoolLocation) fmt.Println(SchoolName)}
复制代码


在运行这个文件时,它能够访问 data.go 中所有导出的和未导出的字段,因为两者都在同一个包模型中。没有编译错误,它的输出如下:

&{test 21}&{}21testtest21Model Package:test21&{test 21}testsomecitytest
复制代码


让我们把上述文件 test.go 移到另一个名为 view 的包中。现在注意运行 go build 的输出。它给出了编译错误。所有的编译错误都是由于不能引用未导出的字段造成的:


package view
import "fmt"
//Test functionfunc Test() { //STRUCTURE IDENTIFIER p := &model.Person{ Name: "test", age: 21, } fmt.Println(p) c := &model.company{} fmt.Println(c) //STRUCTURE'S METHOD fmt.Println(p.GetAge()) fmt.Println(p.getName()) //STRUCTURE'S FIELDS fmt.Println(p.Name) fmt.Println(p.age) //FUNCTION person2 := model.GetPerson() fmt.Println(person2) companyName := model.getCompanyName() fmt.Println(companyName) //VARIBLES fmt.Println(model.companyLocation) fmt.Println(model.CompanyName)}
复制代码


输出:

test.go:13:3: unknown field 'age' in struct literal of type model.Persontest.go:17:8: cannot refer to unexported name model.companytest.go:17:8: undefined: model.companytest.go:22:15: p.getName undefined (cannot refer to unexported field or method model.(*Person).getName)test.go:26:15: p.age undefined (cannot refer to unexported field or method age)test.go:31:17: cannot refer to unexported name model.getCompanyNametest.go:31:17: undefined: model.getCompanyNametest.go:35:14: cannot refer to unexported name model.companyLocationtest.go:35:14: undefined: model.companyLocation
复制代码


发布于: 刚刚阅读数: 4
用户头像

宇宙古今无有穷期,一生不过须臾,当思奋争 2020-05-07 加入

🏆InfoQ写作平台-签约作者 🏆 混迹于江湖,江湖却没有我的影子 热爱技术,专注于后端全栈,轻易不换岗 拒绝内卷,工作于外企开发,弹性不加班 热衷分享,执着于阅读写作,佛系不水文 同名公众号:《宇宙之一粟》

评论

发布
暂无评论
深入理解 Go 语言中的封装机制_Go_宇宙之一粟_InfoQ写作社区