web-dev-qa-db-ja.com

Go-langで構造体への参照を返す

私は次のコードでいくつかの思考の問題を抱えています

package main

import (
    "fmt"
)

type Company struct {
    Name string
    Workers []worker
}

type worker struct {
    Name string
    Other []int
}

func (cmp *Company) NewWorker(name string) worker {
    wrk := worker{Name: name}
    cmp.Workers = append(cmp.Workers, wrk)
    return wrk
}

func main() {
    cmp := Company{}
    cmp.Name = "Acme"
    wrk := cmp.NewWorker("Bugs")
    for i := 1; i <= 10; i++ {
        wrk.Other = append(wrk.Other, i)
    }
    fmt.Println(wrk)
    fmt.Println(cmp)
}

https://play.golang.org/p/Bja7u148mg

ご覧のとおり、コードは私が作成しているワーカーではなく、そのコピーを返しています。実際の労働者を返すにはどうすればよいですか? *と&のいくつかのバリエーションをさまざまなワーカーで試しましたが、次のいずれかになります。

invalid indirect of worker literal (type worker)

または:

cannot use wrk (type worker) as type *worker in return argument

これを行う方法に関するアイデアはありますか?

8
Johan
_func (cmp *Company) NewWorker(name string) *worker {
    wrk := worker{Name: name}
    cmp.Workers = append(cmp.Workers, wrk)
    return &wrk
}
_

_&_は常に「アドレスを取る」を意味します(バイナリビット演算子バージョンを除く)。 _*_は、コンテキストによって意味が変わります。式_*Type_は、「タイプへのポインター」を意味します。表現_*Pointer_は、「ポインターが指すオブジェクト」を意味します。 _invalid indirect of worker literal_という式を使用しようとすると、_*wrk_が返されるのはこのためです。「wrkが指すオブジェクトを教えて」と言っているのに、wrkがポインターではないためです。

そのため、戻り値の型として_*worker_(ワーカーへのポインターを返す)が必要であり、返す構造体のアドレスである_&wrk_を返します。

もう1つの方法は、組み込みのnew()を使用して、最初にポインターを作成することです。

_func (cmp *Company) NewWorker(name string) *worker {
    wrk := new(worker)
    wrk.Name = name
    cmp.Workers = append(cmp.Workers, *wrk)
    return wrk // wrk is a pointer here
}
_

とはいえ、ここでワーカー構造へのポインターを返す理由はほとんどありません。構造体自体には2つのフィールドしかなく、どちらも既に参照型です(文字列は基本的に不変のスライスです)。したがって、構造体全体の長さは5マシンワード(20ビットまたは40バイト、32ビットか32ビットか)によって異なります。 64ビット)。戻り後に構造体を変更するのではなく、Company構造体に格納するバージョンもコピーです(Companyは、ワーカーへのポインターのスライスではなく、ワーカーのスライスを保持します)。

17
Kaedys