博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go语言公开或未公开的标识符
阅读量:6980 次
发布时间:2019-06-27

本文共 2947 字,大约阅读时间需要 9 分钟。

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

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

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

例如下面的代码

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

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

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

func main() {    counter := counters.alertCounter(10)    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(10)    fmt.Printf("Counter: %d\n", counter)}

运行结果如下:

Counter: 10

将工厂函数命名为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: 20}}// --- package main ---func main() {    v := a.NewStu() // OK,v 的类型是 stu,虽然 stu 对包外不可见    fmt.Println(v)}

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

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

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

v1 type: counters.alertCounter

 

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

A short variable declaration uses the syntax:

IdentifierList := ExpressionList

 

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

 

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: 10,    }    a.Name = "Bill"    a.Email = "bill@email.com"    fmt.Printf("User: %v\n", a)}

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

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

转载于:https://www.cnblogs.com/dcz2015/p/10103484.html

你可能感兴趣的文章
Java字节码(.class文件)格式详解(一)
查看>>
【存储】virident 卡使用手册
查看>>
[WSE]如何启用WSE2.0的强大的Trace功能
查看>>
nginx location在配置中的优先级
查看>>
深入浅出TCP协议的三次握手过程
查看>>
树莓派连接WiFi
查看>>
关系数据库的范式和反范式设计
查看>>
【MySql】开机自动启动mysql服务
查看>>
UIKit 框架之UIDatePicker
查看>>
自定义带图标文本的块状态、条状菜单
查看>>
加载SpriteBuilder中的scene为何不能带后缀
查看>>
封装用于解析NSDate的便利的类
查看>>
Java中的模板模式
查看>>
EnterpriseDB & PostgreSQL RLS & Oracle VPD
查看>>
USRP N210实现的整个属性树结构
查看>>
保护模式汇编系列之四 - 段页式内存管理(二)
查看>>
【Scheme归纳】5 数据结构
查看>>
【Java数据结构】链表
查看>>
More Effective C++ 读书笔记六——临时对象
查看>>
Spring的容器内部事件发布
查看>>