Go语言公开或未公开的标识符的基本概念

Go语言支持从包里公开或者隐藏标志符,通过这个特性,可以让用户按照自己的规则控制标识符的可见性。

Go语言中的可见性,是通过声明类型的大小写来进行区别的。

例如下面的代码

// Package counters provides alert counter support.
package counters type alertCounter int

这里 alertCounter 就是外部不可见的,

此时如果在main包中的main方法想要访问这个内部的类型,就会出现下面的问题:

func main() {
counter := counters.alertCounter()
fmt.Printf("Counter: %d\n", counter)
}

不能引用未公开的名字

cannot refer to unexported name counters.alertCounter

规则详细如下:

一个标识符的名字以小写字母开头时,这个标识符就是未公开的,即包外的代码不可见。

一个标识符的名字以大写字母开头时,这个标识符就是公开的,即被包外的代码可见。

那么问题出现了,如果我想要访问这个alertCounter怎么办。我们在C#和java当中也遇到过,想要访问一个private的对象,我们当时使用的是 Get和Set方法,对对象进行取值和赋值。

func New(value int) alertCounter {
return alertCounter(value)
}

此时再通过main方法调用New方法,就可以得到一个alertCount的对象了

func main() {
// 虽然 main.alertCounter 是一个未导出的标识符
// 但是可以用短变量声明操作符捕获未导出类型的变量
counter := counters.New()
fmt.Printf("Counter: %d\n", counter)
}

运行结果如下:

Counter: 

将工厂函数命名为New 是Go 语言的一个习惯。这个New 函数做了些有意思的事情:它创建了一个未公开的类型的值,并将这个值返回给调用者。

为什么这个New能够执行?

要让这个行为可行,需要两个理由。

第一,公开或者未公开的标识符,不是一个值。

第二,短变量声明操作符,有能力捕获引用的类型,并创建一个未公开的类型的变量。(这句话就是上面 counter := counters.New(10) counter就是那个未公开类型的变量)永远不能显式创建一个未公开的类型的变量,不过短变量声明操作符可以这么做。看下面的例子。

// --- package a ---
type stu struct {
name string
age int
}
func NewStu() stu {
return stu{name: "a", age: }
}
// --- package main ---
func main() {
v := a.NewStu() // OK,v 的类型是 stu,虽然 stu 对包外不可见
fmt.Println(v)
}

我们打印一下,上面的短变量声明后的counter的类型

func main() {
// 虽然invisible.count是一个未导出的标识符
// 但是可以用短变量声明操作符捕获未导出类型的变量
counter := counters.New()
fmt.Println("v1 type:", reflect.TypeOf(counter))
fmt.Printf("Counter: %d\n", counter)
}

结果正如我们所想:记住alertCounter是不能进行实例化的哦。

v1 type: counters.alertCounter

补充一:上面的第二点其实是短变量声明的一个有趣的地方,什么是短变量声明

https://blog.csdn.net/wo198711203217/article/details/60574503

http://wenchao.wang/2017/10/23/Go%20%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A0%E6%B1%87%E6%80%BB/

A short variable declaration uses the syntax:

IdentifierList := ExpressionList

补充二:Golang - var 和 := 的使用

https://studygolang.com/articles/5294

Go语言中公开和未公开标识符对类型提升的影响

例子1

package entities

// User defines a user in the program.
type User struct {
Name string
email string
}

User是entities包中公开的类型,Name是公开的成员、email是未公开的成员

在main包调用一下

func main() {
// Create a value of type User from the entities package.
u := entities.User{
Name: "Bill",
email: "bill@email.com",
} fmt.Printf("User: %v\n", u)
}

提示了一个错误:unknown field 'email' in struct literal of type entities.User (but does have entities.email) ,这说明啊,即使User是公开的,它里面的成员如果是隐藏的,对于外面也是非公开的不能被访问

例子2

增加一个Admin公开 user变为非公开 Admin里面使用user作为嵌入,其他成员都是公开的

// Package entities contains support for types of
// people in the system.
package entities // user defines a user in the program.
type user struct {
Name string
Email string
} // Admin defines an admin in the program.
type Admin struct {
user // The embedded type is unexported.
Rights int
}

main

func main() {
a := entities.Admin{
Rights: ,
}
a.Name = "Bill"
a.Email = "bill@email.com" fmt.Printf("User: %v\n", a)
}

可以看到在创建a对象的时候,user是不可见的,但是a却能访问Name和Email两个user内的成员

换句话说,内部类型的公开类型对于外部类型也是公开的。

Go语言公开或未公开的标识符的更多相关文章

  1. 微软未公开的 SP

    一些用在SQL 2000的企业管理GUI中,并且不打算用于其他的流程.微软已预计将其中的一些存储过程从未来的SQL Server版本中删除(或已经删除了).虽然这些存储过程可能很有用并为你节省了很多时 ...

  2. 可怕!CPU暗藏了这些未公开的指令!

    大家好,我是轩辕. 我们知道,我们平时编程写的高级语言,是经过编译器编译以后,变成了CPU可以执行的机器指令: 而CPU能支持的指令,都在它的指令集里面了. 很久以来,我都在思考一个问题: CPU有没 ...

  3. (转载)MS SQL Server 未公开的加密函数有哪些?

    MS SQL Server 未公开的加密函数有哪些? 以下的文章是对MS SQL Server 未公开的加密函数的具体操作,如果你对其相关的实际操作有兴趣的话,你就可以点击了. MS SQL Serv ...

  4. SQL Server里一些未公开的扩展存储过程

    SQL Server里一些未公开的扩展存储过程 [转帖] 博客天地 www.inbaidu.com SQL Server里一些未公开的扩展存储过程 扩展存储过程(xp)是直接运行在SQL Server ...

  5. 利用未公开API获取终端会话闲置时间(Idle Time)和登入时间(Logon Time)

    利用未公开API获取终端会话闲置时间(Idle Time)和登入时间(Logon Time)作者:Tuuzed(土仔)   发表于:2008年3月3日23:12:38 版权声明:可以任意转载,转载时请 ...

  6. CListCtrlEx:一个支持文件拖放和实时监视的列表控件——用未公开API函数实现Shell实时监视

    一.需求无论何时,当你在Explorer窗口中创建.删除或重命名一个文件夹/文件,或者插入拔除移动存储器时,Windows总是能非常快速地更新它所有的视图.有时候我们的程序中也需要这样的功能,以便当用 ...

  7. blktrace未公开选项网络保存截取数据

    本文链接地址: blktrace未公开选项网络保存截取数据 我们透过blktrace来观察io行为的时候,第一件事情需要选择目标设备,以便分析该设备的io行为.具体使用可以参考我之前写的几篇:这里 这 ...

  8. 关于 Android 中未公开的类(用@hide隐藏的类)

    关于 Android 中未公开的类(用@hide隐藏的类) 摘自:http://wangsheng2008love.blog.163.com/blog/static/78201689201142643 ...

  9. PB Event ID 含义 内容浅析2 未公开的数据窗口事件

    原网址:https://www.cnblogs.com/lenya/archive/2010/11/12/3706971.html  (作者:Mark   Brown)         到目前为止,P ...

随机推荐

  1. Django---forms表单使用(2)

    Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1.创建Form类 from dja ...

  2. Android Camera2 预览功能实现

    1. 概述 最近在做一些关于人脸识别的项目,需要用到 Android 相机的预览功能.网上查阅相关资料后,发现 Android 5.0 及以后的版本中,原有的 Camera API 已经被 Camer ...

  3. WPF开发为按钮提供添加,删除和重新排列ListBox内容的功能

    介绍 我有一种情况,我希望能够将项目添加到列表中,并在列表中移动项目,这似乎是使用a的最简单方法ListBox.我立刻想到了如何以通用的方式做到这一点,然后,也许,可以使用行为来做到这一点.这似乎是一 ...

  4. Kotlin入门(33)运用扩展属性

    进行App开发的时候,使用震动器要在AndroidManifest.xml中加上如下权限: <!-- 震动 --> <uses-permission android:name=&qu ...

  5. java之日志管理

    一. 为什么要使用日志 二. 常见日志框架介绍 三. Logback+SLF4J实战 四. 项目源码下载 五. 参考文章   一. 为什么要使用日志 1. 对IT安全至关重要   当您使用强大的日志管 ...

  6. 2019Java查漏补缺(三)

    1.为什么这个public的类的类名必须和文件名相同    是为了方便虚拟机在相应的路径中找到相应的类所对应的字节码文件    2.java8 的一些新特性:     3: 数据库隔离级别 隔离级别 ...

  7. shell脚本批量ssh登陆主机并执行命令

    shell脚本批量ssh登陆主机并执行命令 今天在客户现场遇到了这个问题,客户没有管理工具,无法批量登陆主机下发命令,几个个C段啊,让我一个一个登陆,.................. 所以写了个s ...

  8. SQLServer之删除函数

    删除函数注意事项 从当前数据库中删除一个或多个用户定义函数.DROP 函数支持本机编译的标量用户定义函数. 如果数据库中存在引用 DROP FUNCTION 的 Transact-SQL 函数或视图并 ...

  9. SQL 创建分区表

    (以项目中实际使用的GNSS库为例) 背景:数据量巨大,定时创建月表存放数据,月表中数据存放在不同的文件组中来提高查询效率   一.创建数据库,添加文件组 除了逻辑文件和物理文件的分离之外,SQL S ...

  10. linux内核调试技巧之一 dump_stack【转】

    在内核中代码调用过程难以跟踪,上下文关系复杂,确实让人头痛 调用dump_stack()就会打印当前cpu的堆栈的调用函数了. 如此,一目了然的就能看到当前上下文环境,调用关系了 假设: 遇到uvc_ ...