在 Go 中导出标识符

wentingrohwer · 2018-04-16 13:35:11 · 2177 次点击 · 预计阅读时间 3 分钟 · 大约8小时之前 开始浏览    
这是一个创建于 2018-04-16 13:35:11 的文章,其中的信息可能已经有所发展或是发生改变。

包由单个目录内的源文件组成。 在这样的目录中,从不同的包中获取文件是非法的。 在 Go 中开始每个源文件的 Package 语句定义了文件所属的包:

package foo

package 语句不是引入新标识符的声明,因此以后在源文件中不能使用 "foo"。

包的名称具有类似于常规标识符的语法。 所有共享相同包名的文件形成包。

为了使用来自其他包裹的标识符,需要 import 声明:

import "fmt"

import 关键字后指定的字符串称为导入路径。 它需要唯一标识一个包。 标准库中的软件包使用较短的导入路径,但一般的包,比如 github.com/mlowicki/foo 看起来会更长。

在上面的形式中,通过 package 声明中的包名来完成对导出的标识符的访问。 因此,除了识别属于包的文件外,它还将作为导入声明的默认包名。 通过导入路径之前的标识符可以覆盖它:

import (
    f "fmt"
)
func main() {
    f.Println("whatever")
}

Go 中的作用域中所述,软件包名称的作用域是文件块。

导入后并不是所有包的标识符都可以访问。 只有导出的标识符才可以访问,导出标识符必须遵守的两个规则才能从其他包中直接访问:

  • 标识符的第一个字符是大写字母
  • 要么在包块中定义标识符,要么是字段名称或 method 方法名称

包块的标识符

被定义在软件包块中意味着它被定义在任何功能之外,如:

package library
var V = 1
type S struct {
    Name string
}
type I interface {
    M()
}

V,S 和 I 可用于具有适当导入语句的文件中:

package main
import (
    "fmt"
    "github.com/mlowicki/library"
)
func main() {
    s := library.S{}
    fmt.Println(library.V, s)
}

导出的字段名称

字段名称还必须以大写字母开头,以便从其他包中访问:

package library
type record struct {
    Name string
    age int8
}
func GetRecord() record {
    return record{Name: "Michał", age: 29}
}


package main
import (
    "fmt"
    "github.com/mlowicki/library"
)

func main() {
    record := library.GetRecord()
    fmt.Println(record.Name)
}

上面的代码可以正常工作,但尝试访问未导出的字段 age...

fmt.Println(me.age)

编译时失败:

record.age undefined (cannot refer to unexported field or method age)

在库包中导出结构体,比如改为 Record,但这不会改变任何内容 - 即结构类型仍然不会导出 age 字段。

导出的 method 名称

与字段名称相同的规则适用于 method

package library

import "fmt"

type Duck interface {
    Quack()
    walk()
}

type Record struct{}

func (Record) Quack() {
    fmt.Println("Quack")
}

func (Record) walk() {
    fmt.Println("walk")
}
func GetDuck() Duck {
    return Record{}
}

package main

import (
    "github.com/mlowicki/library"
)

func main() {
    duck := library.GetDuck()
    duck.Quack()
    record := library.Record{}
    record.Quack()
}

输出:

> ./bin/sandbox
Quack
Quack

调用方法 walk 是非法的:

duck.walk()

输出:

duck.walk undefined (cannot refer to unexported field or method walk)

或者:

record.walk()

在编译时会报如下错误:

record.walk undefined (cannot refer to unexported field or method library.Record."".walk)

via: https://medium.com/golangspec/exported-identifiers-in-go-518e93cc98af

作者:Michał Łowicki  译者:wentingrohwer  校对:polaris1119

本文由 GCTT 原创编译,Go语言中文网 荣誉推出


有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2177 次点击  
加入收藏 微博
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传