How to remove a struct value from a struct slice without memory leak?

6,075 views
Skip to first unread message

Aaron

unread,
Sep 25, 2017, 9:25:33 AM9/25/17
to golang-nuts
Newbie here everyone.

I am trying to remove a struct value from a slice, which consists of elements of the same type. Let's say the type is defined as below:

type connInfo struct {
    ipAddr string
    name string
    conn net.Conn
}


Now I have a remove function, in which there is a for loop to find out the struct value position in the slice, and then delete the value. But there is a potential memory leak according to here, and because I can't assign a "nil" value to the struct type, I need to assign a zero value to the last element of the slice. Am I doing it correctly? Or I need to do some smarter thing?

func removeClient(clients []connInfo, connClient *connInfo) {
    for i := len(clients) - 1; i >= 0; i-- {
        if clients[i] == *connClient {
            copy(clients[i:], clients[i+1:])
            clients[len(clients)-1] = connInfo{}
            clients = clients[:len(clients)-1]
        }
    }
}

vital...@gmail.com

unread,
Sep 25, 2017, 10:44:38 AM9/25/17
to golang-nuts
clients = append(clients[:i], clients[i+1:len(clients)]...)

Tamás Gulácsi

unread,
Sep 25, 2017, 2:52:09 PM9/25/17
to golang-nuts
https://github.com/golang/go/wiki/SliceTricks

clients[i] = clients[0]
clients = clients[1:]

Dan Kortschak

unread,
Sep 25, 2017, 8:14:22 PM9/25/17
to Tamás Gulácsi, golang-nuts
This is not nice if you want to reuse the slice, and still may leak the
fields.

clients[i] = clients[len(clients)-1]
// If the current clients[i] is deleted it becomes inaccessible
// and the ipAddr, name and conn fields potentially leak, so
// zero them in the last position of the slice.
clients[len(clients)-1] = connInfo{}
clients = clients[:len(clients)-1]


Keith Randall

unread,
Sep 25, 2017, 8:38:52 PM9/25/17
to golang-nuts
I see a couple of issues with your code.

The code you use for removal of an element is right. You've correctly made sure there is no leak.

You never return the clients slice back to the caller.  Any length shortening of the clients slice will be lost when the function returns.

I'm skeptical of using struct equality on your connInfo struct.  My guess is you just want the ipAddr and name fields to match, not the net.Conn itself.  It's hard for me to know for sure without seeing the users of this code, but it looks fishy.

You probably want a break statement at the end of your if block. Unless you expect multiple structs to match?

Dan Kortschak

unread,
Sep 25, 2017, 9:33:52 PM9/25/17
to Keith Randall, golang-nuts
Just to clarify, this is from context discussing Aaron's code.

On Mon, 2017-09-25 at 17:38 -0700, 'Keith Randall' via golang-nuts
wrote:
> I see a couple of issues with your code.

Aaron

unread,
Sep 25, 2017, 11:11:28 PM9/25/17
to golang-nuts
Thanks I also worried that at the beginning. But when I use this code I find it works correctly. But if I pull it out to test the individual function it doesn't look good. I think you are right the best practice is to return the slice.

For the connInfo struct comparison I learned that comparing them is possible but I don't know how accurate it would be. This is just a simple test. I will look into this issue later.
Reply all
Reply to author
Forward
0 new messages