2017-02-16 5 views
2

それが第一の方法で呼ばれていた場合、コードは動作しますが、この方法は、別のメソッドを呼び出す場合、コードが失敗しているようです。golangの構造体のプロパティであるスライスを追加できないのはなぜですか?私はgolangスライスに値を追加しようとしている

例(Test3は、私はもともとやろうとしていたものです):

package main 

import (
    "fmt" 
) 

// This works 

type Test1 struct { 
    all []int 
} 

func (c Test1) run() []int { 
    for i := 0; i < 2; i++ { 
    c.all = append(c.all, i) 
    } 
    return c.all 
} 

// This works 

var gloabl_all []int 

type Test2 struct {} 

func (c Test2) run() []int { 
    c.combo() 
    return gloabl_all 
} 

func (c Test2) combo() { 
    for i := 0; i < 2; i++ { 
    gloabl_all = append(gloabl_all, i) 
    } 
} 

// This doesn't 

type Test3 struct { 
    all []int 
} 

func (c Test3) run() []int { 
    c.combo() 
    return c.all 
} 

func (c Test3) combo() { 
    for i := 0; i < 2; i++ { 
    c.all = append(c.all, i) 
    fmt.Println("Test3 step", i + 1, c.all) 
    } 
} 

func main() { 
    test1 := &Test1{} 
    fmt.Println("Test1 final:", test1.run(), "\n") 

    test2 := &Test2{} 
    fmt.Println("Test2 final:", test2.run(), "\n") 

    test3 := &Test3{} 
    fmt.Println("Test3 final:", test3.run()) 
} 

この出力:

Test1 final: [0 1] 

Test2 final: [0 1] 

Test3 step 1 [0] 
Test3 step 2 [0 1] 
Test3 final: [] 

遊び場コピー:https://play.golang.org/p/upEXINUvNu

任意の助けをいただければ幸いです!移動中

+0

ポインタ受信機を使用する必要があります。そうしないと、コピーを追加する必要があります。 – Volker

答えて

5

すべてが値によって渡されます。そして、渡された値がコピーされます。

Test3.combo()値(非ポインタ)受信機を有する。

func (c Test3) run() []int { 
    c.combo() 
    return c.all 
} 

func (c Test3) combo() { 
    for i := 0; i < 2; i++ { 
    c.all = append(c.all, i) 
    fmt.Println("Test3 step", i + 1, c.all) 
    } 
} 

これはTest3.combo()c.combo()Test3.run()から呼び出された場合、コピーは(タイプTest3である)cで作られていることを意味します。 combo()メソッドはコピーに対して動作します。 Test3.allには2つの数字が正しく付加されますが、このメソッドが返ってきたらコピーは破棄されます。

そこでTest3.run()戻りc.allスライスがどのTest3.combo()を添付するので、それは、空(nil)スライスを返す場合、コピーの分野であり、これは廃棄されてきました。

ソリューション:

func (c *Test3) combo() { 
    for i := 0; i < 2; i++ { 
    c.all = append(c.all, i) 
    fmt.Println("Test3 step", i + 1, c.all) 
    } 
} 

出力(Go Playground上でそれを試してみてください):

Test1 final: [0 1] 

Test2 final: [0 1] 

Test3 step 1 [0] 
Test3 step 2 [0 1] 
Test3 final: [0 1] 

注受信機の星*func (c *Test3) combo()単にポインタの受信機を使用しています。それを追加することにより、あなたは受信ポインタ作り、combo()が呼び出されたときに、それが唯一のタイプTest3の値へのポインタを受け取り、それは先の尖った値、Test3.run()が持っている値なので、変更しますcombo()戻り、変更は失われません。

+0

これは簡単でした!理にかなって、あなたの助けに感謝しますが、(これも有用であった:https://nathanleclaire.com/blog/2014/08/09/dont-get-bitten-by-pointer-vs-non-pointer-method-receivers-in -golang /) –

関連する問題