Copying structs in Go is very simple, simply by assigning a struct object to another newly declared object, such as:

type Cartoon struct {
	Name string
}
cart1 := Cartoon{"Name": "nezha"}
var cart2 Cartoon
cart2 = cart1
Copy the code

In this way, carT2 copies cart1, and cart1 changes its Name without affecting the value of Cart2.

Now extend the Cartoon structure, first define a Movie interface, and use *Cartoon to realize this interface, then define the structure Video, but use the Video structure to realize the Movie interface, as follows:

type Movie interface{
    Play()
}
func (c *Cartoon)Play(){
    fmt.Println(c.Name)
}

type Video struct {
	Name string
}
func (v Video)Play(){// Video without * fmt.println (v.name)}Copy the code

So how do you dynamically generate a copy of the Movie interface? namely

funct CloneMovie(moive Movie) Movie{
    ???
}
Copy the code

How do you do that?

As mentioned above, when the argument movie is a Struct type (i.e. Reflect. Struct), it can be copied as an assignment. How is this implemented when movie is a pointer variable?

We can get some ideas from Reflect’s features:

  • Reflect.new (reflect.typeof (param)) generates a pointer variable to the param type. For example, if param is Cartoon, this expression produces *Cartoon type, If type is *Cartoon, the result of this expression is **Cartoon type.
  • Reflect.typeof (param).elem () gets the structure type to which the param pointer points (param must be a pointer type, otherwise Elem() will report an error). If param is *Cartoon, then the object returned by this expression is Cartoon.
  • Reflect.valueof (param).elem () gets the ValueOf the structure to which this param pointer points. (Param must be a pointer, otherwise Elem() will report an error.)
  • The Set method of the reflect.Value object implements assignment. The structure obtained in the previous step forms a copy when assigned.

Therefore, it can be implemented as follows:

func Clone(movie Movie)Movie{
	movieType := reflect.TypeOf(movie)
	if movieType.Kind() == reflect.Struct {
		var newOne Movie
		newOne = movie
		return newOne
	}
	ifMovietype.kind () == reflect.ptr {valueType := movietype.elem () // Gets the struct object newMoviePtr := reflect.new (valueType) // Generates a pointer to this structure newMovieptr.elem ().set (reflect.valueof (movie).elem ())return newMoviePtr.Interface().(Movie)
	}
	return nil
}
Copy the code

This method is just a simple implementation idea, more complex structure cloning, can be implemented recursively for the idea.