2012-11-04 11 views
5

Desidero estendere il regexp dalla libreria standard Go per poter definire i miei metodi. Io uso il seguente struct:Sostituire struct wrapping con una dichiarazione di tipo in Go

type RichRegexp struct { 
    *regexp.Regexp 
} 

Come si può vedere, questa struct contiene nient'altro che la avvolto regexp.Regexp. Allora mi chiedo se potevo sostituire questo con una semplice dichiarazione di tipo simile a questo:

type RichRegexp regexp.Regexp 

Ma come avrei dovuto scrivere il seguente func allora?

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

ho cercato di convertire regexp.Regexp al mio RichRegexp ma non ha compilato. Qual è lo schema generale per restituire un tipo personalizzato che avvolge un tipo sottostante?

risposta

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

Anche qui: http://play.golang.org/p/cgpi8z2CfF

5

È possibile utilizzare una conversione, ma in questo caso è necessario, che la definizione di tipo non è un puntatore:

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

Questo è supportato da the spec :

Il tipo di destinatario deve essere nel formato T o * T dove T è un nome di tipo. Il tipo denotato da T è chiamato tipo di base del ricevitore; non deve essere un puntatore o tipo di interfaccia e deve essere dichiarato nello stesso pacchetto come metodo. Il metodo si dice legato al tipo di base e il nome del metodo è visibile solo all'interno di selettori per quel tipo.

Tuttavia, si può fare questo:

type MyRegexp regexp.Regexp 

Come stai gestione dei valori ora, è possibile effettuare le seguenti operazioni:

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

E avete il vostro tipo di espressione regolare.

codice completo in gioco: http://play.golang.org/p/OWNdA2FinN

Come un modello generale, vorrei direi:

  • Se è improbabile che cambi e non è necessario memorizzare valori arbitrari, utilizzare un tipo conversione.
  • Se è necessario memorizzare valori insieme al tipo incorporato, utilizzare struct.
  • Se è probabile che il codice cambi e sia necessario supportare grandi varietà di cose, definire un'interfaccia e non utilizzare la conversione di incorporamento/tipo.
+0

'MyRegexp (* x)' non funziona nel mio caso, poiché devo restituire un puntatore. Se provo 'y: = & MyRegexp (* x)' Ricevo l'errore 'non posso prendere l'indirizzo di MyRegexp (* x)' http://play.golang.org/p/HbVoAVM1RY. – deamon

+1

Se si desidera un puntatore, convertirlo semplicemente in un puntatore di "MyRegexp" in questo modo: '(* MyRegexp) (x)'. Nota che non è più necessario il dereferenciation di 'x', dato che ora ci occupiamo di puntatori. Vedi [le specifiche] (http://golang.org/ref/spec#Conversions) per ulteriori informazioni :) – nemo

+0

Grazie per le tue spiegazioni. '(* MyRegexp) (x)' è anche quello che suggerisce 'jnml'. – deamon

Problemi correlati