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 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示