Callback pattern for handling socket response
I am using a callback pattern and am wondering if this is frowned upon in the Go community.


"callback pattern" shouldn't be frowned upon (they are used in "first-class functions" for instance: https://blog.golang.org/first-class-functions-in-go-and-new-go https://dave.cheney.net/2016/11/13/do-not-fear-first-class-functions)

However regarding your code, I don't think that it looks like idiomatic go code.



Don't just check errors, handle them gracefully

sc.conn, _, err = websocket.DefaultDialer.Dial(u.String(), nil)

if err != nil {
    cb(nil, err)
}


You pass the err to your callback, but you then continue inside the Connect function: if you couldn't dial, why do you continue?



Never start a goroutine without knowing how it will stop


go func() {
    defer sc.conn.Close()
    defer close(done)
    for {
        _, message, err := sc.conn.ReadMessage()
        if err != nil {
            cb(nil, err)
        }
        cb(message, nil)
    }
}()


The inner for loop will never stop (so will your goroutine).



One possibility would be to change it like this:

// SocketResponse function callback for data from socket
type SocketResponse func(res []byte)

// Connect create the connection with the host
func (sc SocketClient) Connect(cb SocketResponse) error {
    u := url.URL{Scheme: "wss", Host: sc.Host, Path: sc.Path}

    var err error
    sc.conn, _, err = websocket.DefaultDialer.Dial(u.String(), nil)

    if err != nil {
        return err
    }

    defer sc.conn.Close()
    for {
        _, message, err := sc.conn.ReadMessage()
        if err != nil {
            return err
        }
        cb(message)
    }
}


Some properties of this code :


on dial error, it stops
it reads all the messages until one error is encountered
it blocks (but go sc.Connect() is easy to write)


Some possible evolutions:


to continue even in case of errors, you could return a channel of errors (and send all errors encountered)
also use a channel to report the received messages
to control when the Connect method should stop, you could use a context or split your method in 3 parts: Connect, ReadMessage &amp; Close