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}
}
1
songray 2023-12-19 17:09:58 +08:00
bro, 这就是闭包.
|
2
lilei2023 2023-12-19 17:13:06 +08:00
虽然不太懂,感觉类似闭包
|
3
body007 2023-12-19 17:54:30 +08:00
复制某个 GPT 的回答。
非导出类型包含导出字段的应用场景是合法的。这种情况通常出现在需要将结构体值传递给其他包以进行处理的情况下。为了让其他包能够访问字段,这些字段必须是导出的,但结构体类型本身可以保持为非导出。 举个例子,假设你想要生成一个 JSON 响应。你可以创建一个非导出的结构体,然后为了能够使用 `encoding/json` 包,结构体的字段必须是导出的。例如: ```go type response struct { Success bool `json:"success"` Message string `json:"message"` Data string `json:"data"` } func myHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json;charset=UTF-8") resp := &response{ Success: true, Message: "OK", Data: "some data", } if err := json.NewEncoder(w).Encode(resp); err != nil { // 处理错误 } } ``` 在这个例子中,`response` 结构体是非导出的,但它包含了导出的字段。这使得我们可以在 `myHandler` 函数中创建 `response` 结构体的实例,并将其传递给 `encoding/json` 包来生成 JSON 响应。 总的来说,非导出类型包含导出字段的应用场景通常出现在需要将结构体值传递给其他包以进行处理的情况下。 |
4
zizon 2023-12-19 17:56:06 +08:00
因为 inner.New 是 exported 的.
类似于 func New() interface{} 加上导出不导出本来就是个编译器的约束. 所以 i.I 也是可以的(I exported). 你可以去提个 issue 争议下算不算 bug... |
5
zizon 2023-12-19 17:58:28 +08:00
说可以是 bug 的原因是它形式上略不同于
func New() interface{} 因为有一个编译期确切的返回类型. |
6
zizon 2023-12-19 18:00:55 +08:00
说不是 bug 的原因在于它算是一种 feature.
需要暴露一个类型/接口,但又不想添加显式的约束(interface type/struct type). 同时又不想给个没有类型约束的 interface{}. 所以等价于一个 public 的接口返回一个不可修改/不可外部构造的类型. |
7
nagisaushio 2023-12-19 18:08:43 +08:00
@body007 你这回答和楼主的问题没有关系,楼主没有在问和字段相关的内容。建议不要瞎贴 GPT 的内容,会被站长枪毙。
|
8
body007 2023-12-19 18:12:43 +08:00
@nagisaushio 就是要讨论字段 I 被导出,外部可以调用,而 inner 类型不是导出的情况,我只是列出了一种场景吧。
|
9
thevita 2023-12-19 18:15:20 +08:00
不能导出的是 inner 这个类型
func New() inner {} , 这个函数是 导出的, 这里的可以理解成一个复合类型 就像 struct Struct { inner inner } 这个 Struct 被导出了,但它作为一个复合类型,内部引用了 inner 一样. |
10
leonshaw 2023-12-19 18:18:35 +08:00
导出不导出指的是 identifier
|
11
kiripeng 2023-12-19 18:19:44 +08:00
写成函数是为了做约束,比如 邮件不愿意外面的得到准确做了模糊处理 xxx**@gmail.com
|
12
hxtheone 2023-12-19 18:21:19 +08:00 via iPhone
虽然这个做法能被编译通过而且也有一定的使用场景, 但是感觉是因为支持闭包留下的一个口子, 如果开了 linter 的话都会被提醒一句 'exported func Outer returns unexported type main.inner, which can be annoying to use’, 像我这种强迫症肯定是会把 inner 改掉的
|