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月前
|
存储 监控 算法
防止员工泄密软件中文件访问日志管理的 Go 语言 B + 树算法
B+树凭借高效范围查询与稳定插入删除性能,为防止员工泄密软件提供高响应、可追溯的日志管理方案,显著提升海量文件操作日志的存储与检索效率。
101 2
|
2月前
|
Java 编译器 Go
【Golang】(1)Go的运行流程步骤与包的概念
初次上手Go语言!先来了解它的运行流程吧! 在Go中对包的概念又有怎样不同的见解呢?
154 4
|
2月前
|
Java 编译器 Go
【Golang】(5)Go基础的进阶知识!带你认识迭代器与类型以及声明并使用接口与泛型!
好烦好烦好烦!你是否还在为弄不懂Go中的泛型和接口而烦恼?是否还在苦恼思考迭代器的运行方式和意义?本篇文章将带你了解Go的接口与泛型,还有迭代器的使用,附送类型断言的解释
180 3
|
2月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
188 1
|
4月前
|
Cloud Native 安全 Java
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
295 1
|
4月前
|
Cloud Native Go API
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
392 0
|
4月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
256 0
|
4月前
|
Cloud Native Java 中间件
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
227 0
|
4月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
327 0
|
4月前
|
数据采集 Go API
Go语言实战案例:多协程并发下载网页内容
本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,讲解如何使用 Goroutine 和 Channel 实现多协程并发抓取网页内容,提升网络请求效率。通过实战掌握高并发编程技巧,构建爬虫、内容聚合器等工具,涵盖 WaitGroup、超时控制、错误处理等核心知识点。

热门文章

最新文章