2016-04-11 11 views
6

Ich kam aus der C++ Welt und in C gehen ++ in der Regel, wenn Sie über die Leistung kümmern, und Sie müssen nicht Sie geändert werdet, Objekt, Sie geben es konstante Referenz mitKonst Referenz in C++ und gleichwertig in Golang

void func(const std::string& str) 

In diesem Fall ist die Zeichenfolge NICHT COPIED und kann in der Funktion nicht geändert werden.

Ich weiß, dass in Go gibt es zwei Möglichkeiten Objekt zu übergeben:

  • von Wert, und dann können Sie nicht ändern (oder tatsächlich kann man aber es macht keinen Sinn), aber es sehr speicheraufwendig
  • Mit Zeiger, dies ist gut aus den Bedingungen des Speichers, aber Sie können Objekt ändern.

Also, was ist der beste Ansatz? Übergeben Sie immer Objekt für Zeiger, auch wenn Sie es nicht ändern möchten, weil es schneller ist? Oder gibt es einige Compiler-Optimierungen und selbst wenn Sie es per Wert senden, wird es manchmal als Referenz gesendet?

+3

Duplizieren: [Konstante Parameter in Golang-Funktion] (http://stackoverflow.com/a/22093762/1734730) –

Antwort

4

Es gibt keine direkte Entsprechung in Go.

  1. Überschreiten Sie den Zeiger, wenn das Objekt groß ist (~ größer als 32-64 Byte) und/oder geändert werden muss.
  2. Übergeben nach Wert, wenn die obige Regel nicht zutrifft.
  3. maps/channels/slices sind Referenztypen, sie enthalten innere Zeiger, so dass Sie sie nicht mit einem Zeiger übergeben müssen, es sei denn, Sie möchten möglicherweise eine Null übergeben oder eine bereits vorhandene Komponente anhängen Scheibe.

Beispiel:

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

Karte/Kanal werden tatsächlich implizit als Referenz übergeben. –

+0

@NipunTalukdar Ja, deshalb habe ich das gesagt, ich schätze, ich sollte es klarer machen. – OneOfOne

+0

Sollte es nicht sein? If * m == nil {'? – siritinga

0

Für Strings können Sie *string als Parameter verwenden, und es scheint, Sie können nicht die Original-Zeichenkette ändern:

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

Drucke:

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

Für komplexe Strukturen wäre es schwieriger oder unmöglich o Pass be ref & Bearbeitung verhindern.

Bitte korrigieren Sie mich, wenn ich es falsch verstanden habe (Ich lerne gerade Go).

+2

Zeichenketten werden als Referenz übergeben, aber sie sind unveränderlich, so dass sie sich verhalten, als ob sie nach Wert übergeben werden. –

+0

@ NickCraig-Wood, bedeutet es, dass, wenn wir eine Zeichenfolge nach Wert wie t1 (s-String) übergeben, es nicht im Speicher kopiert wird und wir können einfach große Strings hin und her übergeben? –

+0

Ja das ist richtig –