是否可以让您从字符串实例化结构?(类似于Ruby在Ruby中的Ruby将字符串名称转换为实际类)
我正在尝试将代码与单个文件分开为子目录,但是在运行go build
时会获得undefined: PngConverter
。这可能是一个负载订单问题,但是现在我试图动态实例化结构。
convert_image.go
var converters = map[string]string{
"png": "PngConverter",
"jpg": "JpegConverter",
"jpeg": "JpegConverter",
}
type Converter interface {
convert(*bytes.Buffer) string
}
func selectConverter(converterName string) {
// dynamically initialize the converter with reflect?
}
func ConvertImageToWords(filename string, image *bytes.Buffer) string {
ext = Ext(filename)
if converterName, y := converters[ext]; y {
converter = selectConverter(converterName)
id = converter.convert(image)
}
return nil
}
converters/png_converter.go
type PngConverter struct {}
func (converter PngConverter) convert(in *bytes.Buffer) string {
// ...
}
converters/jpeg_converter.go
type JpegConverter struct {}
func (converter JpegConverter) convert(in *bytes.Buffer) string {
// ...
}
动态评估
go是编译语言,这意味着没有动态评估,一切都是在编译后完成的。诸如Ruby,Python或JavaScript之类的语言具有eval
(和模拟)函数的动态编程功能,从概念上讲,这对于编译语言是不可能的。
接口作为抽象的惯用方式
如果您需要GO中的通用类型 - 毫无疑问使用接口。另外,您非常接近正确的方法:您不需要从字符串中评估结构而不是它,您应该声明具有所有必需实现的Converter interface
类型对象的地图。
可编译的操场:
var converters map[string]Converter
type Converter interface {
convert(*bytes.Buffer) string
}
type PngConverter struct{}
type JpgConverter struct{}
func (p *PngConverter) convert(b *bytes.Buffer) (repr string) { return }
func (p *JpgConverter) convert(b *bytes.Buffer) (repr string) { return }
func ConvertImageToWords(
filename string,
image *bytes.Buffer,
converters map[string]Converter) (repr string) {
ext := Ext(filename)
if converter, y := converters[ext]; y {
repr = converter.convert(image)
}
return
}
导入和软件包
您尚未被问到,但这是错误的设计:
是的,它们在单独的目录中...
软件包是一个命名空间,您可以拥有多个文件,并且您无需将它们导入另一个文件。软件包是一个目录,其中包含package <name>
作为第一行的GO文件。但是,如果您使用不同的软件包(目录)将文件分开,则需要将其导入,如果需要在另一个软件包中使用它。类似Java的类模块设计对GO不正确。只需将所有转换器和界面保存在同一软件包中。
不,您不能从字符串表示。
初始化struct。参考
您可以做的是通过ConvertImageToWords
中的接口。
func ConvertImageToWords(conv Converter, image *bytes.Buffer) string
或将文件名转换为ConvertImageToWords
中的接口Converter
。
func GetConverter(ext string) Converter {
switch ext {
case "png":
return PngConverter{}
case "jpg":
...
}
func ConvertImageToWords(filename string, image *bytes.Buffer) string {
ext = Ext(filename)
conv := GetConverter(ext)
id := conv.convert(image)
...
}
也最好导出接口方法:
type Converter interface {
Convert(*bytes.Buffer) string
}
参考