2012-11-04 17 views
5

Chcę przedłużyć regexp ze standardowej biblioteki Go, aby móc zdefiniować własne metody. Używam następujące struct:Zastąpienie struktury zawijania deklaracją typu w Go

type RichRegexp struct { 
    *regexp.Regexp 
} 

Jak widać, ta struktura zawiera nic poza zawiniętego regexp.Regexp. Więc zastanawiam się, czy mogę wymienić to z prostej deklaracji typu jak poniżej:

type RichRegexp regexp.Regexp 

Ale jak mam napisać następujący func wtedy?

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

Próbowałem przekonwertować regexp.Regexp do mojego RichRegexp ale nie skompilować. Jaki jest ogólny wzór zwracania niestandardowego typu, który otacza typ podstawowy?

Odpowiedz

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

Również tutaj: http://play.golang.org/p/cgpi8z2CfF

5

Można użyć konwersji, ale w tym przypadku konieczne jest, że definicja typu nie jest wskaźnikiem:

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

ten jest wspierany przez the spec :

Typ odbiornika musi mieć postać T lub * T, gdzie T jest nazwą typu. Typ oznaczony literą T nazywa się podstawowym typem odbiornika; nie może to być wskaźnik ani typ interfejsu i musi być zadeklarowany w tym samym pakiecie jako metoda. Mówi się, że metoda jest związana z typem bazowym , a nazwa metody jest widoczna tylko w selektorach dla tego typu.

Jednak można to zrobić:

type MyRegexp regexp.Regexp 

Jak jesteś obsługi wartości teraz, można wykonać następujące czynności:

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

I masz swój typ regexp.

Pełny kod w grę: http://play.golang.org/p/OWNdA2FinN

Jako ogólny wzór, to powiedziałbym:

  • Jeśli jest to raczej się nie zmieni i nie trzeba przechowywać dowolne wartości, użyj rodzajem konwersja.
  • Jeśli chcesz przechowywać wartości wraz z osadzonym typem, użyj struct.
  • Jeśli Twój kod prawdopodobnie ulegnie zmianie i musi obsługiwać duże odmiany rzeczy, zdefiniuj interfejs i nie używaj konwersji osadzania/typu.
+0

'MyRegexp (* x)' nie działa w moim przypadku, ponieważ muszę zwrócić wskaźnik. Jeśli spróbuję 'y: = & MyRegexp (* x)' otrzymuję błąd 'nie może wziąć adresu MyRegexp (* x)' http://play.golang.org/p/HbVoAVM1RY. – deamon

+1

Jeśli chcesz wskaźnik, po prostu przekonwertuj go na wskaźnik 'MyRegexp', tak jak:' (* MyRegexp) (x) '. Zauważ, że nie ma już wymogu dereferencji "x", ponieważ mamy teraz do czynienia ze wskaźnikami. Zobacz [specyfikację] (http://golang.org/ref/spec#Conversions), aby uzyskać dodatkowe informacje :) – nemo

+0

Dziękuję za wyjaśnienia. '(* MyRegexp) (x)' jest tym, co sugeruje również "jnml". – deamon

Powiązane problemy