2012-11-04 41 views
5

我想從Go標準庫中擴展regexp以便能夠定義我自己的方法。我用下面的結構:在Go中用類型聲明替換包裝結構

type RichRegexp struct { 
    *regexp.Regexp 
} 

正如你所看到的,這個結構包含了什麼,但包裹regexp.Regexp。所以我不知道我是否可以用一個簡單的類型聲明這樣的替換此:

type RichRegexp regexp.Regexp 

但我應該怎麼寫以下FUNC呢?

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? 
} 

我試圖regexp.Regexp轉化爲我的RichRegexp但它並沒有編譯。什麼是返回包裝基礎類型的自定義類型的一般模式?

回答

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") 
} 

另外這裏:http://play.golang.org/p/cgpi8z2CfF

5

您可以使用一個轉換,但在這種情況下,它是必要的,你的類型定義不是指針:

type MyRegexp *regexp.Regexp // Doesn't work 

這是由the spec支持:

接收器類型必須是T或* T形式,其中T是類型名稱。 T表示的類型稱爲接收器基類型; 它不能是 指針或接口類型並且它必須在相同的 封裝的方法中聲明。該方法被稱爲綁定到基類型 ,方法名稱僅在該類型的選擇器中可見。

但是,你可以這樣做:

type MyRegexp regexp.Regexp 

正如你現在正在處理的值,可以做到以下幾點:

x := regexp.MustCompile(".*") 
y := MyRegexp(*x) 

,你有你自己的正則表達式類型。

在作怪

全碼:http://play.golang.org/p/OWNdA2FinN

作爲一種普遍現象,我會想說:

  • 如果它不可能改變,你不需要存儲任意值,使用 類型轉換。
  • 如果需要將值與嵌入類型一起存儲,請使用struct
  • 如果您的代碼有可能發生改變,並需要支持種類繁多的事情, 定義一個接口,並且不使用嵌入/類型轉換。
+0

'MyRegexp(* X)'不中我的情況下工作,因爲我必須返回一個指針。如果我嘗試'y:=&MyRegexp(* x)',我得到錯誤'不能接受MyRegexp(* x)的地址'http://play.golang.org/p/HbVoAVM1RY。 – deamon

+1

如果你想要一個指針,只需將它轉換爲MyRegexp的指針就像這樣:'(* MyRegexp)(x)'。請注意,我們現在正在處理指針,因此不再需要「x」的取消引用。請參閱[規範](http://golang.org/ref/spec#Conversions)獲取更多信息:) – nemo

+0

感謝您的解釋。 '(* MyRegexp)(x)'也是'jnml'所建議的。 – deamon