【发布时间】:2019-08-31 09:30:49
【问题描述】:
我有一个简单类型的数据,它只包含一个 uint32,但是可以对这个数据执行许多操作。使用此数据的所有文件都位于同一个包中,因此可以访问结构内未导出的 uint32,这是不可取的。我最近了解了闭包的强大功能,想知道是使用包含执行任务的函数的结构体,还是将 uint32 存储在结构体中,然后只使用结构体接收器的方法。
这是 OpenGL 着色器的基本表示。方法和闭包选项在调用者看来是一样的,但在后台执行不同。
关闭:
type Shader struct {
getID func() uint32
delete func()
}
func CreateShader(shader string) Shader {
var id uint32
//Do work...
return Shader{
getID: func() uint32 {
return id
},
delete: func() {
gl.DeleteShader(id)
},
}
}
方法:
type Shader struct {
id uint32
}
func CreateShader(shader string) Shader{
var id uint32
//Do work...
return Shader{id: id}
}
func (s Shader) getID() uint32 {
return s.id
}
func (s Shader) delete() {
gl.DeleteShader(s.id)
}
这两个选项在使用中都是这样的:
func main() {
shader := CreateShader("shader.code")
id := shader.getID()
fmt.Println(id)
shader.delete()
}
我想避免的错误使用是调用者可能会在 Shader 不知道的情况下影响 id 类型。类似于:
shader.id = 4102 // or some other change
使用闭包时,这种行为是不可能的,需要调用者使用正确的调用。
如 cmets 中所述,可以使用着色器包并取消导出着色器类型。我没有使用它,因为我认为制作一个完整的包只是为了保存一个文件是不合适的。但是,如果它巩固了对类型的正确使用,也许它是正确的。
与方法相比,闭包版本是否“错误”?是否有任何 golang 标准可以对更适合我的用例的选择进行分类?我希望调用者不要触摸着色器的 id,并认为使用闭包可以更清楚地正确使用着色器类型。
【问题讨论】:
-
您试图通过闭包来防止哪些误用?第二种方法更惯用,因此应该更清楚如何正确使用。
-
为什么没有shader包来封装Shader类型及其方法?
-
如果着色器包只对你的父包有用 - 而不是任何外部代码 - 使用 go internal packages
-
这更多地是关于代码是否是惯用的,而不是关于它的用例。虽然,这是重要的信息。就个人而言,我认为这是一个有趣的闭包用法。这更像是一个例子,而不是一个实际用例,像 Ceris Limon 说,如果使用方法,正确使用是显而易见的。