doumi0737 2019-08-05 10:59
浏览 443
已采纳

使用未导入包中的类型的返回值

Given the following three go packages (I abbreviated the import paths for imp and Tdef for privacy reasons)

package main

import (
        "imp"
        "fmt"
)

func main() {
        T := imp.NewT()
        fmt.Printf("T.X = %d
", T.X)
        fmt.Printf("T has type %T
", T)
}
package imp

import (
        "Tdef"
)

func NewT() Tdef.T {
        return Tdef.T{0,0}
}
package Tdef

type T struct {
        X int
        Y int
}

func (T T) GetX() int {
        return T.X
}

main() produces the output

T.X = 0
T has type Tdef.T

This means that I can use a variable of type T in a package where the definition of T is not visible by defining it using a return value, and I can use its exported fields (and methods, not shown here).

I find that a bit surprising and did not find any information on this in the spec. Then again, I don't have much programming experience -- is this to be expected, and is it bad practice to make use of it (I don't have a real-life example right now, mind you)?

  • 写回答

1条回答 默认 最新

  • duanaidang6197 2019-08-05 11:15
    关注

    You are allowed to use values originating from anywhere, but without the import declaration you can't refer to its type for example. Yes, because referring to identifiers requires a qualified identifier which has the form of:

    QualifiedIdent = PackageName "." identifier .
    

    You haven't imported Tdef in your main package, so you can't refer to the type Tdef.T identifier (type), but you didn't attempt it so all is good.

    Spec: Import declarations:

    An import declaration states that the source file containing the declaration depends on functionality of the imported package (§Program initialization and execution) and enables access to exported identifiers of that package. The import names an identifier (PackageName) to be used for access and an ImportPath that specifies the package to be imported.

    You used a short variable declaration and so you did not specify the variable's type (which is perfectly OK), so you didn't need to refer to its type:

    T := imp.NewT()
    

    T's type will be inferred from the right-hand side expression, which will be Tdef.T of course, but your source code contains no reference to this type. Obviously the following line would give a compile-time error without importing Tdef:

    var T Tdef.T = imp.NewT()
    

    You can even return values of unexported types from an exported function, and the package importing it can as well use it, e.g. it can print it, call exported methods and access exported fields of the value of the unexported type (although returning values of unexported types is considered bad practice, golint gives a warning like: "exported func XXX returns unexported type pkgname.typename, which can be annoying to use").

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥170 如图所示配置eNSP
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改
  • ¥20 wireshark抓不到vlan
  • ¥20 关于#stm32#的问题:需要指导自动酸碱滴定仪的原理图程序代码及仿真
  • ¥20 设计一款异域新娘的视频相亲软件需要哪些技术支持
  • ¥15 stata安慰剂检验作图但是真实值不出现在图上