Why passing struct to function with literal struct parameter from current package differs from the same for function from another package?

huangapple go评论79阅读模式
英文:

Why passing struct to function with literal struct parameter from current package differs from the same for function from another package?

问题

这段代码有两个文件,一个是main.go,另一个是sub/sub.go。在main.go中,定义了一个结构体Struct,并在main函数中调用了Fn函数,传入了Struct{"john"}作为参数。在sub/sub.go中,也定义了一个同名的结构体Struct,并在Fn函数中打印了参数。

问题出现在将Fn函数移动到另一个包sub后。在main.go中,我们需要通过sub.Fn来调用Fn函数。但是,由于main.gosub/sub.go中的Struct结构体虽然同名,但是实际上是不同的类型。因此,编译器会报错,提示无法将Struct结构体作为参数传递给sub.Fn函数。

关于这个问题的更多信息和解释,你可以查看官方文档。

英文:

This works perferctly:

package main

import "fmt"
  
type Struct struct {
	field string
}
func Fn(arg struct{field string}) {
    fmt.Println(arg)
}

func main() {
    Fn(Struct{"john"})
}

But this gives ./main.go:12: cannot use Struct literal (type Struct) as type struct { field string } in argument to sub.Fn:

main.go

package main

import "go_tests/sub"
    
type Struct struct {
	field string
}

func main() {
    sub.Fn(Struct{"john"})
}

sub/sub.go

package sub

import "fmt"

func Fn(arg struct{field string}) {
    fmt.Println(arg)
}

Only change in function call is that Fn(Struct{"john"}) was replaced with sub.Fn(Struct{"john"}).

Why moving function to another package affects types logic? Links to the docs will be appreciated.

答案1

得分: 3

你需要导出你的结构体字段:

type Struct struct {
    Field string
}

然后还需要修改调用,使用导出的字段:

func Fn(arg struct{Field string}) {
    fmt.Println(arg)
}

根据语言规范(具体是最后一句)的规定:

  • 对于结构体字面量,以下规则适用:

    • 键必须是在LiteralType中声明的字段名。
    • 不包含任何键的元素列表必须按照字段声明的顺序列出每个结构体字段的元素。
    • 如果任何元素有一个键,那么每个元素都必须有一个键。
    • 包含键的元素列表不需要为每个结构体字段都有一个元素。省略的字段将获得该字段的零值。
    • 字面量可以省略元素列表;这样的字面量将求值为其类型的零值。
    • 为不同包中的结构体的非导出字段指定元素是错误的。
英文:

You need to export your struct field:

type Struct struct {
    Field string
}

and then also change the call to use the exported field:

func Fn(arg struct{Field string}) {
    fmt.Println(arg)
}

From the language spec (specifically the last sentence):

> For struct literals the following rules apply:
>
> - A key must be a field name declared in the LiteralType.
> - An element list that does not contain any keys must list an element for each struct field in the order in which the fields are declared.
> - If any element has a key, every element must have a key.
> - An element list that contains keys does not need to have an element for each struct field. Omitted fields get the zero value for that
> field.
> - A literal may omit the element list; such a literal evaluates to the zero value for its type.
> - It is an error to specify an element for a non-exported field of a struct belonging to a different package.

huangapple
  • 本文由 发表于 2015年4月16日 01:41:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/29657109.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定