2012-12-20 6 views
12

私はこのGo:あまりにも多くの値を作成していますか?

type myStruct struct { 
    mystring string 
    myint int 
} 

のような構造体を持っている場合、私は私が最初にそれを返す前に「s」が変数に格納しますので、この

func New() myStruct { 
    s := myStruct{} 

    s.mystring = "string" 
    s.myint = 1 

    return s 
} 

のような新しい体mystructを返す関数を持っている場合、私の関数は実際に2つのmyStruct値を1つではなく作成していますか?

もしそうなら、最初にそれを変数に保存しないようにするのが良い方法ですか?

+0

私はわからないんだけど、私は、構文は次のようにあった覚え 'FUNC新()(S myStruct){...} 'これは結果の割り当てを行います。それはより速いかもしれません。 googleやgccgoを使っていますか? –

+0

Google goコマンドを使用しています。その構文が同じ効果を持つかどうか、または何らかの形で問題が回避されるのであれば私は興味があります。 –

+0

受理された答えを参照してください... 'func New()(s myStruct)'として定義すると、関数本体に入る前にコンパイラが構造体を割り当てることができます。それはjdiからの答えと同じように動作するはずです。依然としてあなたは確信が持てません。なぜなら、スペック/実装の実行が永久に変化しているからです。 –

答えて

11

return文はmyStructオブジェクト値のコピーを返します。それが小さいオブジェクトなら、これは問題ありません。

呼び出し側がこのオブジェクトを変更できるようにするために、あなたが意図して、構造体は、レシーバとしてポインタを使用する方法があるとすれば、それは代わりに構造体へのポインタを返すために、より理にかなって:

func New() *myStruct { 
    s := myStruct{} 

    s.mystring = "string" 
    s.myint = 1 

    return &s 
} 

あなたはポインタの戻り値の型対値のメモリアドレスを比較するときは、コピーが起こって見ることができます:http://play.golang.org/p/sj6mivYSHg

package main 

import (
    "fmt" 
) 

type myStruct struct { 
    mystring string 
    myint int 
} 

func NewObj() myStruct { 
    s := myStruct{} 
    fmt.Printf("%p\n", &s) 

    return s 
} 

func NewPtr() *myStruct { 
    s := &myStruct{} 
    fmt.Printf("%p\n",s) 
    return s 
} 

func main() { 

    o := NewObj() 
    fmt.Printf("%p\n",&o) 

    p := NewPtr() 
    fmt.Printf("%p\n",p) 
} 


0xf8400235a0 // obj inside NewObj() 
0xf840023580 // obj returned to caller 
0xf840023640 // ptr inside of NewPtr() 
0xf840023640 // ptr returned to caller 
+0

ありがとう、この特定のケースで私はmyStruct関数のシグネチャに 's'を宣言しない限り、コピーを返すのが正しいと思われますが、これは動作が異なるようです。 –

+0

ああ、メモリアドレスを見ると、私のために完全にクリアされます。どうもありがとう! –

+0

HaはPythonの答えから多くを学びました。あなたのGoの答えから学びました。できるならもう一度+1します。 – RocketDonkey

3

私は間違いなくGoのエキスパートではありませんが、@ max.haredoomで述べたように、関数シグネチャ自体に変数を割り当てることができます。このように、あなたもreturnsを省略することができます:私はEffective Goで渡ってきた例では

package main 

import "fmt" 

type myStruct struct { 
    mystring string 
    myint int 
} 

func New() (s myStruct) { 
    s.mystring = "string" 
    s.myint = 1 

    return 
} 

func main() { 
    r := New() 
    fmt.Println(r) 
} 

// Outputs {string 1} 

を、このような性質の物事の最も一般的な方法であるように見えるが、やはりん、私は実際には主題に関する権威ではない(そして実際のパフォーマンスに関する追加情報を探す)。

+0

ありがとうございます。元のバージョンがコピーを作成していたことがわかったと思いますが、同じバージョンを使って同じテストを行っても、そのコピーは回避されているようです。私が使ったテストですが、あなたのソリューションで更新されました。 http://play.golang。org/p/66mqsVFbs_ –

+0

暗黙のリターンであまりにも狂っていない、ほとんどの場合、彼らは悪い習慣になる傾向がある – jozefg

+0

@jozefgええ、良い点:) – RocketDonkey

0

私は、延期を使用して答えを見つけたと思います。

myStruct値の遅延修正があるように関数を更新しました。これは、返品後に発生することを意味しますが、反対側で返品される前に発生します。

これを行うと、呼び出し側が受け取った構造体には更新された値が表示されないため、実際にコピーを返すように見えます。

func New() myStruct { 
    s := myStruct{} 

    defer func() { 
     s.mystring = "new value" // defer an update to the value 
    }() 

    s.mystring = "string" 
    s.myint = 1 

    return s 
} 

func main() { 

    b := New() 

    fmt.Println(b) // still shows the original value 
} 

http://play.golang.org/p/WWQi8HpDny

関連する問題