Go语言导出包解密:外部访问你的类型和值

简介: Go语言导出包解密:外部访问你的类型和值

一、概述

Go 语言实现封装和可见性控制的主要方式是通过标识符的首字母大小写来决定其是否可被其他包访问。

标识符如果首字母大写就可以被外部包访问(导出), 可以选择性地控制包内代码的对外可见性。

本文介绍如何导出包中的标识符,让外部包可以访问包内定义的类型、变量、常量、函数、导出类型注意事项。

主要内容包括

  • 导出标识符的规则
  • 导出类型的注意事项
  • 导出结构体字段的方法
  • 导出函数的注意事项
  • 内部包的使用
  • 示例:导出图形数学包中的类型与函数

通过本文可了解 Go 语言的可见性控制机制,掌握包内代码导出的方法,在编写 Go 程序时合理控制代码的对外接口。


 

二、导出标识符的规则

Go 语言中,如果标识符首字母大写,则可以被同一个包内的其他文件访问,也可以被其他包访问。称为导出(export)标识符。

例如在 util 包中定义


package util
var PrivateVariable int 
type PublicType struct{}
func privateFunction(){}
func PublicFunction(){}

其他包导入 util 后


import "util"
util.PublicFunction() // okutil.PublicType // ok
util.privateFunction() // errorutil.PrivateVariable // error

由此可见,只有PublicFunctionPublicType可被外部访问,私有标识符不能访问。

结论就是,Go 语言通过首字母大小写来决定标识符的对外可见性,这是 Go 语言中实现封装和信息隐藏的主要方式。


 

三、导出类型的注意事项

导出自定义的类型时,需要注意

1、类型名要大写,如PublicType struct{}

2、类型内嵌的其他类型也应该是可导出的


type publicType1 struct{} 
type PublicType2 struct {  publicType1 // 嵌套的类型也应该可导出}

3、结构体字段如果要导出,则必须是可导出类型,并且大写首字母。


type MyStruct struct {  PublicField1 int  publicField2 int // error,小写不能导出}


 

四、导出结构体字段的方法

导出一个结构体类型时,外部代码可以访问到该结构体类型本身,但是默认情况下无法访问该类型的字段。如果需要导出结构体字段,必须将字段首字母设置为大写。

例如


package data
type User struct {  ID int  Name string }
type Product struct {  id int //小写,不能被外部访问  Name string}

其他包中


import "data"
var u data.User 
u.ID = 1 // OKu.Name = "John" // OK
var p data.Productp.id = 1  //错误,不能访问p.Name = "Apples" // OK

结构体类型导出后,默认情况下外部代码只能访问类型本身,不能访问非导出字段。

若是想让外部代码访问结构体字段,必须将字段首字母大小写切换为大写即可。


 

五、导出函数的注意事项

导出函数也有以下注意事项:

1、函数名需要大写首字母。

2、函数参数和返回值类型必须是可导出的。


func ExportFunc(param PublicType) PublicType {  //...}

3、若是函数返回多个值,所有返回值类型都必须可导出:


func ExportMulti(int) (PublicType, error) {  // ...}


 

六、内部包

若是希望包内代码完全不被其他包访问,可以将包命名以 _ 下划线开头,称为内部包。

例如:


import _ "myapp/internal/tools"

tools包中的代码完全不可被外部访问。

这通常用于一些程序内部使用的包,外部不需要访问的场景。


 

七、示例:导出图形数学包中的类型与函数

下面创建一个图形数学相关的math包,其中包含计算周长和面积的函数,示例导出该包中的类型与函数。


package math
import "math"
// Point 是二维坐标类型type Point struct {  X, Y float64}
// Circle 是圆类型type Circle struct {  Center Point //圆心  Radius float64 //半径}
// Perimeter计算图形的周长func Perimeter(graph Object) float64 {  switch g := graph.(type) {    case Circle:      return 2 * math.Pi * g.Radius    case Rectangle:      return 2*g.Width + 2*g.Height  }  return 0}
// Area计算图形的面积func Area(graph Object) float64 {  switch g := graph.(type) {    case Circle:      return math.Pi * g.Radius * g.Radius    case Rectangle:      return g.Width * g.Height  }  return 0}

在其他包中可以如下使用:


import "math"
circle := math.Circle{  Center: math.Point{X: 0, Y:0},  Radius: 5, }
math.Perimeter(circle) //可以调用math.Area(circle)

由此可见,将包内的类型名和函数名首字母大写,可以选择性地导出这些标识符,让外部包根据需要访问使用。

如果类型名和函数名首字母小写,则无法被外部访问。这便实现了良好的封装性。


 

八、总结

Go 语言通过标识符首字母大小写来控制对外可访问性,实现了封装和信息隐藏:

大写首字母标识符可被外部包访问(导出)

小写首字母标识符不能被外部包访问(非导出)

要导出类型需要将类型名弄成大写开头,嵌套类型和结构体字段也要导出类型。

导出函数同样要将函数名大写,参数和返回值也必须是可导出类型。

合理地导出包内代码,可以让外部有选择地访问和使用包提供的功能,是一个好的 Go 语言编程实践。


目录
相关文章
|
2天前
|
JavaScript Java Go
探索Go语言在微服务架构中的优势
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出。本文将深入探讨Go语言在构建微服务时的性能优势,包括其在内存管理、网络编程、并发模型以及工具链支持方面的特点。通过对比其他流行语言,我们将揭示Go语言如何成为微服务架构中的一股清流。
|
2天前
|
SQL 关系型数据库 MySQL
go语言中安装数据库驱动
【11月更文挑战第1天】
15 5
|
2天前
|
编译器 Go 开发者
go语言中导入相关包
【11月更文挑战第1天】
10 3
|
3天前
|
测试技术 Go
go语言中测试工具
【10月更文挑战第22天】
13 4
|
3天前
|
SQL 关系型数据库 MySQL
go语言中数据库操作
【10月更文挑战第22天】
14 4
|
3天前
|
缓存 前端开发 中间件
go语言中Web框架
【10月更文挑战第22天】
14 4
|
2天前
|
关系型数据库 MySQL 数据库连接
go语言中打开数据库连接
【11月更文挑战第1天】
12 2
|
6天前
|
Serverless Go
Go语言中的并发编程:从入门到精通
本文将深入探讨Go语言中并发编程的核心概念和实践,包括goroutine、channel以及sync包等。通过实例演示如何利用这些工具实现高效的并发处理,同时避免常见的陷阱和错误。
|
3天前
|
安全 测试技术 Go
Go语言中的并发编程模型解析####
在当今的软件开发领域,高效的并发处理能力是提升系统性能的关键。本文深入探讨了Go语言独特的并发编程模型——goroutines和channels,通过实例解析其工作原理、优势及最佳实践,旨在为开发者提供实用的Go语言并发编程指南。 ####
|
7天前
|
安全 网络协议 Go
Go语言网络编程
【10月更文挑战第28天】Go语言网络编程
96 65