英文:
Replace wrapping struct with a type declaration in Go
问题
我想扩展Go标准库中的regexp
,以便能够定义自己的方法。我使用以下结构体:
type RichRegexp struct {
*regexp.Regexp
}
如你所见,这个结构体除了包装的regexp.Regexp
之外没有其他内容。所以我想知道是否可以用一个简单的类型声明来替代它,像这样:
type RichRegexp regexp.Regexp
但是接下来我应该如何编写以下函数呢?
func Compile(expression string) (*RichRegexp, error) {
regex, err := regexp.Compile(expression)
if err != nil {
return nil, err
}
return &RichRegexp{regex}, nil // 如何实现这个?
}
我尝试将regexp.Regexp
转换为我的RichRegexp
,但它无法编译通过。返回一个包装了底层类型的自定义类型的一般模式是什么?
英文:
I want to extend the regexp
from the Go standard library to be able to define my own methods. I use the following struct:
type RichRegexp struct {
*regexp.Regexp
}
As you can see, this struct contains nothing but the wrapped regexp.Regexp
. So I wonder whether I could replace this with a simple type declaration like this:
type RichRegexp regexp.Regexp
But how should I write the following func then?
func Compile(expression string) (*RichRegexp, error) {
regex, err := regexp.Compile(expression)
if err != nil {
return nil, err
}
return &RichRegexp{regex}, nil // How to do this?
}
I tried to convert regexp.Regexp
to my RichRegexp
but it didn't compile. What is the general pattern to return a custom type which wraps a underlying type?
答案1
得分: 5
你可以使用类型转换,但在这种情况下,你的类型定义不能是指针:
type MyRegexp *regexp.Regexp // 不起作用
这是由规范支持的:
接收器类型必须是T或*T的形式,其中T是类型名称。
T所表示的类型称为接收器基本类型;它不能是指针或接口类型,并且必须在同一个包中声明。
该方法被绑定到基本类型,并且该方法名仅在该类型的选择器中可见。
然而,你可以这样做:
type MyRegexp regexp.Regexp
由于你现在处理的是值,你可以这样做:
x := regexp.MustCompile(".*")
y := MyRegexp(*x)
然后你就有了自己的正则表达式类型。
完整代码请参见:http://play.golang.org/p/OWNdA2FinN
作为一般模式,我会说:
- 如果不太可能改变且不需要存储任意值,请使用类型转换。
- 如果需要将值与嵌入类型一起存储,请使用
struct
。 - 如果你的代码可能会改变并且需要支持各种各样的事物,请定义一个接口,不要使用嵌入/类型转换。
英文:
You can use a conversion, but in this case it is necessary, that your type definition is not a pointer:
type MyRegexp *regexp.Regexp // Doesn't work
This is backed by the spec:
> The receiver type must be of the form T or *T where T is a type name.
> The type denoted by T is called the receiver base type; it must not be
> a pointer or interface type and it must be declared in the same
> package as the method. The method is said to be bound to the base type
> and the method name is visible only within selectors for that type.
However, you can do this:
type MyRegexp regexp.Regexp
As you're handling values now, you can do the following:
x := regexp.MustCompile(".*")
y := MyRegexp(*x)
And you have your own regexp type.
Full code at play: http://play.golang.org/p/OWNdA2FinN
As a general pattern, I would would say:
- If it's unlikely to change and you don't need to store arbitrary values, use
a type conversion. - If you need to store values along with your embedded type, use a
struct
. - If your code is likely to change and needs to support large varieties of things,
define an interface and don't use embedding / type conversion.
答案2
得分: 3
package main
import (
"regexp"
)
type RichRegexp regexp.Regexp
func Compile(expression string) (*RichRegexp, error) {
regex, err := regexp.Compile(expression)
if err != nil {
return nil, err
}
return (*RichRegexp)(regex), nil
}
func main() {
Compile("foo")
}
英文:
package main
import (
"regexp"
)
type RichRegexp regexp.Regexp
func Compile(expression string) (*RichRegexp, error) {
regex, err := regexp.Compile(expression)
if err != nil {
return nil, err
}
return (*RichRegexp)(regex), nil
}
func main() {
Compile("foo")
}
Also here: http://play.golang.org/p/cgpi8z2CfF
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论