• Go语言公开或未公开的标识符


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

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

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

    例如下面的代码

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

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

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

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

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

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

  • 相关阅读:
    python json模块出现Invalid control character这个异常的原因
    KMS服务,使用命令激活windows/office
    vscode Python文件头部信息
    MIMIC-III Clinical Database 翻译
    autohotkey 设置
    DeepLearning 写代码常用
    VScode 个人设置
    随机种子设置
    samba配置
    jieba 分词不显示日志
  • 原文地址:https://www.cnblogs.com/dcz2015/p/10103484.html
Copyright © 2020-2023  润新知