Golang Go语言中大小写对导出的影响

发布于 1周前 作者 ionicwang 来自 Go语言
package inner

type inner struct { I int }

func New() inner { return inner{I: 1} }

package outter

import (
	"testing"
)

func TestGet(t *testing.T) {
	i := inner.New()
	t.Log(i.I)
}

inner 是小写,理论上不应该被外部能访问,但是通过一个大写的函数,却把它暴露出来了。今天第一次看到这个写法,有点惊讶。

之前我一般都是下面两种写法:

package inner

type Inner interface { Get() int }

type inner struct { i int }

func (i *inner) Get() int { return i.i }

func New() Inner { return &inner{i: 1} }

package inner

type Inner struct {
	I int
}

func New() Inner {
	return Inner{I: 1}
}

Golang Go语言中大小写对导出的影响

更多关于Golang Go语言中大小写对导出的影响的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

13 回复

bro, 这就是闭包.

更多关于Golang Go语言中大小写对导出的影响的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


虽然不太懂,感觉类似闭包

复制某个 GPT 的回答。

非导出类型包含导出字段的应用场景是合法的。这种情况通常出现在需要将结构体值传递给其他包以进行处理的情况下。为了让其他包能够访问字段,这些字段必须是导出的,但结构体类型本身可以保持为非导出。

举个例子,假设你想要生成一个 JSON 响应。你可以创建一个非导出的结构体,然后为了能够使用 encoding/json 包,结构体的字段必须是导出的。例如:

go<br>type response struct {<br> Success bool `json:"success"`<br> Message string `json:"message"`<br> Data string `json:"data"`<br>}<br><br>func myHandler(w http.ResponseWriter, r *http.Request) {<br> w.Header().Set("Content-Type", "application/json;charset=UTF-8")<br> resp := &amp;response{<br> Success: true,<br> Message: "OK",<br> Data: "some data",<br> }<br> if err := json.NewEncoder(w).Encode(resp); err != nil {<br> // 处理错误<br> }<br>}<br>

在这个例子中,response 结构体是非导出的,但它包含了导出的字段。这使得我们可以在 myHandler 函数中创建 response 结构体的实例,并将其传递给 encoding/json 包来生成 JSON 响应。

总的来说,非导出类型包含导出字段的应用场景通常出现在需要将结构体值传递给其他包以进行处理的情况下。

因为 inner.New 是 exported 的.

类似于 func New() interface{}

加上导出不导出本来就是个编译器的约束.
所以 i.I 也是可以的(I exported).

你可以去提个 issue 争议下算不算 bug…

说可以是 bug 的原因是它形式上略不同于
func New() interface{}

因为有一个编译期确切的返回类型.

说不是 bug 的原因在于它算是一种 feature.

需要暴露一个类型/接口,但又不想添加显式的约束(interface type/struct type).
同时又不想给个没有类型约束的 interface{}.

所以等价于一个 public 的接口返回一个不可修改/不可外部构造的类型.

你这回答和楼主的问题没有关系,楼主没有在问和字段相关的内容。建议不要瞎贴 GPT 的内容,会被站长枪毙。

就是要讨论字段 I 被导出,外部可以调用,而 inner 类型不是导出的情况,我只是列出了一种场景吧。

不能导出的是 inner 这个类型

func New() inner {} , 这个函数是 导出的, 这里的可以理解成一个复合类型

就像

struct Struct {
inner inner
}

这个 Struct 被导出了,但它作为一个复合类型,内部引用了 inner 一样.

导出不导出指的是 identifier

写成函数是为了做约束,比如 邮件不愿意外面的得到准确做了模糊处理 xxx**@gmail.com

虽然这个做法能被编译通过而且也有一定的使用场景, 但是感觉是因为支持闭包留下的一个口子, 如果开了 linter 的话都会被提醒一句 'exported func Outer returns unexported type main.inner, which can be annoying to use’, 像我这种强迫症肯定是会把 inner 改掉的

在Go语言中,大小写对导出的影响是一个非常重要的概念,它直接关系到包的封装性和模块化设计。

首先,需要明确的是,Go语言使用大小写敏感的方式来区分标识符的导出性。如果一个标识符(如变量、函数、类型等)的首字母大写,那么它就是导出的(exported),可以被其他包访问和使用。相反,如果首字母小写,则它是未导出的(unexported),只能在定义它的包内部访问。

这种设计有几个好处:

  1. 封装性:通过控制标识符的导出性,可以隐藏包的内部实现细节,只暴露必要的接口给外部使用。这有助于减少包的依赖性和复杂度。

  2. 模块化:未导出的标识符可以被视为模块的私有成员,而导出的标识符则构成模块的公共接口。这有助于实现代码的模块化和可重用性。

  3. 命名冲突:由于未导出的标识符在包外部不可见,因此不同包之间即使存在相同名称的未导出标识符,也不会导致命名冲突。

在实际开发中,应该遵循Go语言的这一设计原则,合理使用大小写来控制标识符的导出性。对于库和框架的开发者来说,更是需要精心设计包的公共接口,确保既提供了足够的功能,又保持了良好的封装性和模块化设计。

总之,大小写对导出的影响是Go语言中的一个重要特性,它有助于实现代码的封装性、模块化和可维护性。

回到顶部