Unable to read from UNIX socket using net.Conn.Read

I am trying to do simple UNIX-socket communication with GO. I have an existing service that binds to a named socket on disk, and I want GO to interact with it through this interface. For testing, I used Netcat to create such a named socket

$ nc -vlU /tmp/sock
Bound on /tmp/sock
Listening on /tmp/sock
...

The GO code just opens the socket and writes to it and reads from it in a rate-limited loop

package main

import (
    "net"
    "fmt"
    "time"
)

func main() {
    ctl, err := net.Dial("unix", "/tmp/sock")
    if err != nil {
        fmt.Printf("err: %v\n", err)
        return
    }

    buf := make([]byte, 0, 256)
    for {
        time.Sleep(time.Second)
        ctl.Write([]byte("test write\n"))
        n, err := ctl.Read(buf)
        fmt.Printf("len:%v, data:%v, err:%v\n", n, buf, err)
    }
}

I see the writes coming through in the Netcat console:

$ nc -vlU /tmp/sock
Bound on /tmp/sock
Listening on /tmp/sock
Connection received on /tmp/sock
test write
test write
test write
...

But the GO-side of things just loops endlessly while returning a zero length and no error.

$ go run test.go
len:0, data:[], err:<nil>
len:0, data:[], err:<nil>
len:0, data:[], err:<nil>
len:0, data:[], err:<nil>
len:0, data:[], err:<nil>
...

So, the writes are observed in the Netcat console and are therefore working. But what is going on with the reads? Because the net.Dial interface allows setting a timeout, I was expecting the net.Conn.Read operation to be a blocking one.

What am I doing wrong?

Turns out this is the behavior observed when you attempt to read into a zero length buffer. That is,

buf := make([]byte, 0, N)

versus

buf := make([]byte, N)

You should have written

buf := make([]byte, 0, 256)
for {
	// ...
	n, err := ctl.Read(buf[:cap(buf)])
	buf = buf[:n]
    if err != nil {
        // handle error
    }
    // ...
}

What does buf[:256] mean for a buffer with no length?

buf[:256]sets a new length for buf when 256 <= cap(buf):

buf = buf[0:256:cap(buf)]


package main

import "fmt"

func main() {
	buf := make([]byte, 0, 256)
	fmt.Println(len(buf), cap(buf))
	buf = buf[:256]
	fmt.Println(len(buf), cap(buf))
}

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

0 256
256 256

References:

Go Blog: Go Slices: usage and internals

The Go Programming Language Specification: Slice expressions