Shutting down listening socket server

With the help of forum members I created this simple “echo” server with support of graceful stop: when stop requested, already opened connections correctly processed before exit.

I’m wondering if this implementation is good enough or there are some potential issues? Here is the code

package main

import (
	"fmt"
	"net"
	"os"
	"sync"
	"time"
)

type Server struct {
	listener  *net.TCPListener
	quit      chan bool
	waitGroup *sync.WaitGroup
}

func NewService() *Server {
	addr, err := net.ResolveTCPAddr("tcp4", ":9999")
	if err != nil {
		fmt.Println("Failed to resolve address", err.Error())
		os.Exit(1)
	}

	listener, err := net.ListenTCP("tcp", addr)
	if err != nil {
		fmt.Println("Failed to create listener", err.Error())
		os.Exit(1)
	}

	srv := &Server{
		listener:  listener,
		quit:      make(chan bool),
		waitGroup: &sync.WaitGroup{},
	}
	go srv.serve()
	return srv
}

func (srv *Server) serve() {
	for {
		select {
		case <-srv.quit:
			fmt.Println("Stop listening for new clients")
			srv.listener.Close()
			return
		default:
		}
        srv.listener.SetDeadline(time.Now().Add(1e9))
        conn, err := srv.listener.AcceptTCP()
        if err != nil {
            if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
                continue
            }
            fmt.Println("Failed to accept connection:", err.Error())
        }
        srv.waitGroup.Add(1)
        go srv.handleConnection(conn)
	}
}

func (srv *Server) handleConnection(conn net.Conn) error {
	fmt.Println("Accepted connection from", conn.RemoteAddr())

	defer func() {
		fmt.Println("Closing connection from", conn.RemoteAddr())
		conn.Close()
        srv.waitGroup.Done()
	}()

	buf := make([]byte, 1024)
	_, err := conn.Read(buf)
	if err != nil {
		fmt.Println("Read error", err.Error())
		conn.Close()
	}

	_, err = conn.Write(buf)
	if err != nil {
		fmt.Println("Write error", err.Error())
		conn.Close()
	}

	return nil
}

func (srv *Server) Stop() {
	fmt.Println("Stop requested. Waiting for existing connections...")
	close(srv.quit)
	srv.waitGroup.Wait()
	fmt.Println("Stopped successfully")
}

func main() {
	srv := NewService()
	time.Sleep(100 * time.Second)
	srv.Stop()
}

Also I tried to to implement slightly different approach using workers reading from channel. As I understrand this is more idiomatic way of handling multiple connections. Is this a correct implementation too?

package main

import (
	"fmt"
	"net"
	"os"
	"sync"
	"time"
)

var conns chan net.Conn

type Server struct {
	listener  *net.TCPListener
	quit      chan bool
	waitGroup *sync.WaitGroup
}

func NewService() *Server {
	addr, err := net.ResolveTCPAddr("tcp4", ":9999")
	if err != nil {
		fmt.Println("Failed to resolve address", err.Error())
		os.Exit(1)
	}

	listener, err := net.ListenTCP("tcp", addr)
	if err != nil {
		fmt.Println("Failed to create listener", err.Error())
		os.Exit(1)
	}

	srv := &Server{
		listener:  listener,
		quit:      make(chan bool),
		waitGroup: &sync.WaitGroup{},
	}

    conns = make(chan net.Conn, 50)

    for i := 0; i < 5; i ++ {
        fmt.Println("Start worker", i)
        srv.waitGroup.Add(1)
        go handleConnection(srv.waitGroup)
    }

	go srv.serve()
	return srv
}

func (srv *Server) serve() {
	for {
		select {
		case <-srv.quit:
			fmt.Println("Stop listening for new clients")
			srv.listener.Close()
            close(conns)
			return
		default:
		}
        srv.listener.SetDeadline(time.Now().Add(1e9))
        conn, err := srv.listener.AcceptTCP()
        if err != nil {
            if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() {
                continue
            }
            fmt.Println("Failed to accept connection:", err.Error())
        }
        conns <- conn
	}
}

func handleConnection(wg *sync.WaitGroup) {
    defer wg.Done()

    buf := make([]byte, 1024)

    for conn := range conns {
    	fmt.Println("Accepted connection from", conn.RemoteAddr())

        _, err := conn.Read(buf)
        if err != nil {
            fmt.Println("Read error", err.Error())
            conn.Close()
        }

        _, err = conn.Write(buf)
        if err != nil {
            fmt.Println("Write error", err.Error())
            conn.Close()
        }

        fmt.Println("Closing connection from", conn.RemoteAddr())
        conn.Close()
    }
}

func (srv *Server) Stop() {
	fmt.Println("Stop requested. Waiting for existing connections...")
	close(srv.quit)
	srv.waitGroup.Wait()
	fmt.Println("Stopped successfully")
}

func main() {
	srv := NewService()
	time.Sleep(100 * time.Second)
	srv.Stop()
}