[golang] 構造体(struct)のdeepcopy
golangで構造体のdeepcopyを行う方法のメモです。
ポインタをメンバに持った構造体のdeepcopyをgolangだとどんな感じでできるのか気になったので調べてみました。
deepcopy
package main
import (
"github.com/getlantern/deepcopy"
)
type Sample struct {
Value *string
}
func main() {
v := "abc"
sample := &Sample{Value: &v}
sampleCopy := new(Sample)
deepcopy.Copy(sampleCopy, sample)
*sampleCopy.Value = "ABC"
println(*sample.Value) // "abc"
println(*sampleCopy.Value) // "ABC"
}
第一引数に、コピー先、第二引数にコピー元を渡してあげます。
実装
どんな実装で、deepcopyを実装しているのか気になったので中身を覗いてみました。
package deepcopy
import (
"encoding/json"
"fmt"
)
// Make a deep copy from src into dst.
func Copy(dst interface{}, src interface{}) error {
if dst == nil {
return fmt.Errorf("dst cannot be nil")
}
if src == nil {
return fmt.Errorf("src cannot be nil")
}
bytes, err := json.Marshal(src)
if err != nil {
return fmt.Errorf("Unable to marshal src: %s", err)
}
err = json.Unmarshal(bytes, dst)
if err != nil {
return fmt.Errorf("Unable to unmarshal into dst: %s", err)
}
return nil
}
ものすごくシンプルな実装でした。
一旦json.Marshal
でjsonのバイト列を作成してから、json.Unmarshal
で構造体に戻しているようです。
これなら、参照値をメンバに持つ構造体でもdeepcopyされるので安心です。
だた、構造体のメンバにjson:"-"
のようなアノテーションを付けていると、そのメンバはコピーされなくなってしまうので注意が必要かもしれません。