Home > OS >  Best practise for changing an objects value inside struct array
Best practise for changing an objects value inside struct array

Time:09-13

I dont't know if this is necessary for learning phase of a language but please enlighten me about this subject.

I have an array of struct as var movies []Movie and i am building a CRUD API project with golang.

When i start to write updateHandler which handling PUT requests to /movies/{id} endpoint, I couldn't help myself to think other ways of updating an object inside movies array.

The original way (in the tutorial video) was :

// loop over the movies, range
// delete the movie with the id that comes inside param
// add a new movie - the movie that we send in the body of request

for index, item := range movies {
    if item.ID == params["id"] {
        movies = append(movies[:index], movies[index 1:]...)

        var updatedMovie Movie
        json.NewDecoder(r.Body).Decode(&updatedMovie)

        updatedMovie.ID = params["id"]
        movies = append(movies, updatedMovie)
        json.NewEncoder(w).Encode(updatedMovie)
    }
}

but before i watch i tried to write my own method which is below :

for index, item := range movies {
    if item.ID == params["id"] {
        oldMovie := &movies[index]

        var updatedMovie Movie
        json.NewDecoder(r.Body).Decode(&updatedMovie)

        oldMovie.Isbn = updatedMovie.Isbn
        oldMovie.Title = updatedMovie.Title
        oldMovie.Director = updatedMovie.Director

        json.NewEncoder(w).Encode(oldMovie) // sending back oldMovie because it has the id with it
    }
}

As you can see i assigned the pointer of array's index to a variable which named as oldMovie.

I also think about another way too but it didn't go quite well

var updatedMovie Movie
json.NewDecoder(r.Body).Decode(&updatedMovie)

// this linq package is github.com/ahmetalpbalkan/go-linq from here

oldMovie := linq.From(movies).FirstWithT(func(x Movie) bool {
    return x.ID == params["id"]
}).(Movie) 

// But here we'r only assigning the value not the reference(or address or pointer) 
// so whenever i try to get all movies it still returning 
// the old movie list not the updated one

oldMovie.Isbn = updatedMovie.Isbn
oldMovie.Title = updatedMovie.Title
oldMovie.Director = updatedMovie.Director

json.NewEncoder(w).Encode(oldMovie)

Here I have something going around my head is there a possible way to do it like the last way (I couldnt put & to the beginning of linq) even if there is a way what would be the best practice ?

Should I do it like the first way (delete the struct which we want to change and insert the updated one) or maybe the second way (assign the address of struct inside array and change it) or the third way which same as the second (at least in my thoughts) but just using linq package which is i love to read and write ?

CodePudding user response:

The first case you included removes the selected item from a slice, and then appends the new one. This requires a potentially large memmove with seemingly no real purpose.

The second case you have works, but there is a far easier way to do it if the intent is to replace the contents of the object:

for index, item := range movies {
    if item.ID == params["id"] {
        json.NewDecoder(r.Body).Decode(&movies[index])
        // This will send back the updated movie
        json.NewEncoder(w).Encode(&movies[index]) 
        // This will send back the old movie
        json.NewEncoder(w).Encode(item)
        break // Break here to stop searching
    }
}

The third snippet does not return a pointer, so you cannot modify the slice.

  • Related