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 语言编程实践。


目录
相关文章
|
5天前
|
存储 JSON 监控
Viper,一个Go语言配置管理神器!
Viper 是一个功能强大的 Go 语言配置管理库,支持从多种来源读取配置,包括文件、环境变量、远程配置中心等。本文详细介绍了 Viper 的核心特性和使用方法,包括从本地 YAML 文件和 Consul 远程配置中心读取配置的示例。Viper 的多来源配置、动态配置和轻松集成特性使其成为管理复杂应用配置的理想选择。
23 2
|
4天前
|
Go 索引
go语言中的循环语句
【11月更文挑战第4天】
13 2
|
4天前
|
Go C++
go语言中的条件语句
【11月更文挑战第4天】
15 2
|
8天前
|
程序员 Go
go语言中的控制结构
【11月更文挑战第3天】
84 58
|
7天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
4天前
|
Go
go语言中的 跳转语句
【11月更文挑战第4天】
12 4
|
4天前
|
JSON 安全 Go
Go语言中使用JWT鉴权、Token刷新完整示例,拿去直接用!
本文介绍了如何在 Go 语言中使用 Gin 框架实现 JWT 用户认证和安全保护。JWT(JSON Web Token)是一种轻量、高效的认证与授权解决方案,特别适合微服务架构。文章详细讲解了 JWT 的基本概念、结构以及如何在 Gin 中生成、解析和刷新 JWT。通过示例代码,展示了如何在实际项目中应用 JWT,确保用户身份验证和数据安全。完整代码可在 GitHub 仓库中查看。
17 1
|
8天前
|
Go 数据处理 API
Go语言在微服务架构中的应用与优势
本文摘要采用问答形式,以期提供更直接的信息获取方式。 Q1: 为什么选择Go语言进行微服务开发? A1: Go语言的并发模型、简洁的语法和高效的编译速度使其成为微服务架构的理想选择。 Q2: Go语言在微服务架构中有哪些优势? A2: 主要优势包括高性能、高并发处理能力、简洁的代码和强大的标准库。 Q3: 文章将如何展示Go语言在微服务中的应用? A3: 通过对比其他语言和展示Go语言在实际项目中的应用案例,来说明其在微服务架构中的优势。
|
8天前
|
Go 数据处理 调度
探索Go语言的并发模型:Goroutines与Channels的协同工作
在现代编程语言中,Go语言以其独特的并发模型脱颖而出。本文将深入探讨Go语言中的Goroutines和Channels,这两种机制如何协同工作以实现高效的并发处理。我们将通过实际代码示例,展示如何在Go程序中创建和管理Goroutines,以及如何使用Channels进行Goroutines之间的通信。此外,本文还将讨论在使用这些并发工具时可能遇到的常见问题及其解决方案,旨在为Go语言开发者提供一个全面的并发编程指南。
|
5天前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。