2016-04-11 15 views
6

mi è venuto a passare dal mondo C++ e in C++ di solito quando vi preoccupate per le prestazioni e non è necessario obiettate di essere cambiato, si passa con riferimento costanteConst di riferimento in C++ ed equivalente in Golang

void func(const std::string& str) 

In questo caso, la stringa NON È COPIATA e non può essere modificata nella funzione.

so, che in Go ci sono due modi per passare oggetto:

  • per valore, e quindi non è possibile modificare (o in realtà si può, ma non ha senso), ma è molto consumo di memoria
  • Per puntatore, questo è valido dai termini della memoria, ma è possibile modificare l'oggetto.

Quindi, qual è l'approccio migliore? Passa sempre oggetto per puntatore anche se non vuoi modificarlo perché è più veloce? O ci sono alcune ottimizzazioni del compilatore e anche se lo si invia per valore a volte viene inviato come riferimento?

+3

Duplicato: [Parametro costante nella funzione golang] (http://stackoverflow.com/a/22093762/1734730) –

risposta

4

Non c'è un equivalente diretto in Go.

  1. Passare dal puntatore se l'oggetto è grande (~ maggiore di 32-64 byte) e/o richiede la modifica.
  2. Passa al valore se la regola precedente non si applica.
  3. mappe/canali/sezioni sono tipi di riferimento, contengono puntatori interni, quindi non è necessario passarli per puntatore a meno che non si preveda di passare un nil o di voler aggiungere (non modificare elementi già contenuti) ad un fetta.

Esempio:

func doMap(m *map[string]string) { 
    if *m == nil { 
     *m = map[string]string{} 
    } 
    ..... 
} 
+0

mappa/canale sono in realtà implicitamente passati per riferimento. –

+0

@NipunTalukdar sì è per questo che l'ho detto, immagino che dovrei renderlo più chiaro. – OneOfOne

+0

Non dovrebbe essere 'if * m == nil {'? – siritinga

0

Per le stringhe è possibile utilizzare *string come parametro e sembra non è possibile modificare la stringa originale:

package main 

import (
    "fmt" 
    ) 

func t1(s *string) { 
    fmt.Println("Inside before: %s", *s) 
    s2 := "tEsT1" 
    s = &s2 
    fmt.Println("Inside after 1: %s", *s) 
} 

func main() { 
    var s = "test" 
    fmt.Println("Ourside before: %v", s) 
    t1(&s) 
    fmt.Println("Ourside after: %v", s) 
} 

Stampe:

Ourside before: %v test 
Inside before: %s test 
Inside after 1: %s tEsT1 
Ourside after: %v test 

Per le strutture complesse sarebbe più difficile o impossibile o passare essere rif & impedire la modifica.

Per favore correggimi se ho sbagliato (sto solo imparando Go).

+2

le stringhe vengono passate per riferimento, ma sono immutabili e si comportano come se fossero passati per valore. –

+0

@ NickCraig-Wood, vuol dire che se passiamo una stringa in base al valore come la stringa t1 (s) non viene copiata in memoria e possiamo facilmente passare enormi stringhe avanti e indietro? –

+0

Sì, è giusto –